ref #6774 Adapt to service layer changes
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / featuretree / e4 / FeatureTreeEditor.java
index cd89232c1cf4b2a8acac83804b29a25407fd99c7..26969d86979201133986ca20c12fd0ef245b75e1 100644 (file)
@@ -9,8 +9,8 @@
 
 package eu.etaxonomy.taxeditor.featuretree.e4;
 
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -19,32 +19,54 @@ import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.e4.ui.di.Focus;
 import org.eclipse.e4.ui.di.Persist;
+import org.eclipse.e4.ui.di.UISynchronize;
 import org.eclipse.e4.ui.model.application.ui.MDirtyable;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
 import org.eclipse.e4.ui.services.EMenuService;
+import org.eclipse.e4.ui.workbench.modeling.EPartService;
 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.util.LocalSelectionTransfer;
+import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IMemento;
 
 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
-import eu.etaxonomy.cdm.model.description.FeatureNode;
-import eu.etaxonomy.cdm.model.description.FeatureTree;
+import eu.etaxonomy.cdm.api.service.ITermService;
+import eu.etaxonomy.cdm.model.description.Character;
+import eu.etaxonomy.cdm.model.term.FeatureNode;
+import eu.etaxonomy.cdm.model.term.FeatureTree;
+import eu.etaxonomy.cdm.model.term.TermType;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.editor.definedterm.TermTransfer;
+import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
+import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
+import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
+import eu.etaxonomy.taxeditor.featuretree.e4.operation.AddFeatureOperation;
 import eu.etaxonomy.taxeditor.model.AbstractUtility;
-import eu.etaxonomy.taxeditor.model.MessagingUtils;
+import eu.etaxonomy.taxeditor.model.IContextListener;
+import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
+import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
+import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
-import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
+import eu.etaxonomy.taxeditor.store.AppModelId;
 import eu.etaxonomy.taxeditor.store.CdmStore;
-import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
+import eu.etaxonomy.taxeditor.store.StoreUtil;
 import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
 
 /**
@@ -53,8 +75,9 @@ import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
  * @date 06.06.2017
  *
  */
-public class FeatureTreeEditor implements ICdmEntitySessionEnabled,
-               ModifyListener, ISelectionChangedListener, IE4ViewerPart {
+public class FeatureTreeEditor implements IFeatureTreeEditor, ISelectionChangedListener,
+        IE4ViewerPart, IPartContentHasDetails, IPartContentHasSupplementalData,
+        IContextListener, IConversationEnabled, IDirtyMarkable {
 
     private ConversationHolder conversation;
 
@@ -66,81 +89,127 @@ public class FeatureTreeEditor implements ICdmEntitySessionEnabled,
     @Inject
     private MDirtyable dirty;
 
-    private FeatureTreeEditorComposite composite;
+    @Inject
+    private UISynchronize sync;
+
+    @Inject
+    private MPart thisPart;
+
+    private TreeViewer viewer;
 
     @Inject
     public FeatureTreeEditor() {
+        CdmStore.getContextManager().addContextListener(this);
     }
 
-       /** {@inheritDoc} */
     @PostConstruct
     public void createControl(Composite parent, EMenuService menuService){
         if (CdmStore.isActive()){
-            if(conversation == null){
-                conversation = CdmStore.createConversation();
-            }
-            if(cdmEntitySession!=null){
-                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
-            }
+            initSession();
         }
         else{
             return;
         }
-        composite = new FeatureTreeEditorComposite(parent, SWT.NULL);
-        composite.init(new FeatureNodeDragListener(composite.getViewer()),
-                new FeatureNodeDropAdapter(dirty, composite.getViewer()), this, new SelectionAdapter() {
-                    @Override
-                    public void widgetSelected(SelectionEvent e) {
-                        if(isDirty()){
-                            if(MessagingUtils.confirmDialog("Editor has to be saved", "You have to save before loading another feature tree. Save now?")){
-                                save();
-                            }
-                            else{
-                                return;
-                            }
-
-                        }
-                        FeatureTree tree = FeatureTreeSelectionDialog.select(composite.getDisplay().getActiveShell(), conversation, null);
-                        if (tree != null) {
-                            composite.setSelectedTree(tree, FeatureTreeEditor.this);
-                        }
-                    }
-                });
+        parent.setLayout(new FillLayout());
+        viewer = new TreeViewer(parent);
+        viewer.setContentProvider(new FeatureTreeContentProvider());
+        viewer.setLabelProvider(new FeatureTreeLabelProvider());
+
+        int ops = DND.DROP_COPY | DND.DROP_MOVE;
+        Transfer[] transfers = new Transfer[] {
+                FeatureNodeTransfer.getInstance(),
+                TermTransfer.getInstance(),
+                LocalSelectionTransfer.getTransfer()};
+        viewer.addDragSupport(ops, transfers, new FeatureNodeDragListener(viewer));
+        viewer.addDropSupport(ops, transfers, new FeatureTreeDropAdapter(this, viewer, sync));
+        viewer.addSelectionChangedListener(this);
+        viewer.getTree().addKeyListener(new KeyAdapter() {
+            @Override
+            public void keyPressed(KeyEvent e) {
+                if(e.stateMask == SWT.MOD1 && e.keyCode == 'c'){
+                    copy(viewer.getStructuredSelection());
+                }
+                else if(e.stateMask == SWT.MOD1 && e.keyCode == 'v'){
+                    paste(viewer.getStructuredSelection());
+                }
+            }
+        });
+
+        List<FeatureTree> trees = CdmStore.getService(IFeatureTreeService.class).list(FeatureTree.class, null, null, null, null);
+        Collections.sort(trees, (tree1, tree2) -> tree1.getTitleCache().compareTo(tree2.getTitleCache()));
+        viewer.setInput(trees);
 
         //create context menu
-        menuService.registerContextMenu(composite.getViewer().getControl(), "eu.etaxonomy.taxeditor.store.popupmenu.featureTreeEditor");
+        menuService.registerContextMenu(viewer.getControl(), AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_STORE_POPUPMENU_FEATURETREEEDITOR);
     }
 
-       public void setDirty(boolean isDirty){
-           this.dirty.setDirty(isDirty);
-       }
+    public void paste(IStructuredSelection selection) {
+        if (StoreUtil.promptCheckIsDirty(this)) {
+            return;
+        }
 
-       public boolean isDirty(){
-           return dirty.isDirty();
-       }
+        ISelection clipBoardSelection = LocalSelectionTransfer.getTransfer().getSelection();
+        Object firstElement = selection.getFirstElement();
+        FeatureNode parentNode = null;
+        if(firstElement instanceof FeatureNode){
+            parentNode = (FeatureNode) firstElement;
+        }
+        else if(firstElement instanceof FeatureTree){
+            parentNode = ((FeatureTree)firstElement).getRoot();
+        }
+        if(parentNode!=null){
+            FeatureNode copiedNode = (FeatureNode) ((IStructuredSelection)clipBoardSelection).getFirstElement();
+
+            AddFeatureOperation operation = new AddFeatureOperation(copiedNode.getTerm().getUuid(), parentNode, this, this);
+            AbstractUtility.executeOperation(operation, sync);
+        }
 
-    public FeatureTree getSelectedFeatureTree(){
-        return composite.getFeatureTree();
     }
 
-       /** {@inheritDoc} */
+    public void copy(IStructuredSelection selection) {
+        LocalSelectionTransfer.getTransfer().setSelection(selection);
+    }
+
+    private void initSession(){
+        if(conversation == null){
+            conversation = CdmStore.createConversation();
+        }
+        if(cdmEntitySession==null){
+            cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
+        }
+    }
+
+    private void clearSession() {
+        if(conversation!=null){
+            conversation.close();
+            conversation = null;
+        }
+        if(cdmEntitySession != null) {
+            cdmEntitySession.dispose();
+            cdmEntitySession = null;
+        }
+        dirty.setDirty(false);
+    }
+
+       public void setDirty(boolean isDirty){
+           this.dirty.setDirty(isDirty);
+       }
+
        @Override
-       public void modifyText(ModifyEvent e) {
-           composite.getFeatureTree().setTitleCache(composite.getText_title().getText(), true);
-               setDirty(true);
+    public boolean isDirty(){
+           return dirty.isDirty();
        }
 
-       /** {@inheritDoc} */
        @Override
        public void selectionChanged(SelectionChangedEvent event) {
                //propagate selection
-               selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event));
+               selService.setSelection(event.getSelection());
        }
 
        @Focus
        public void focus(){
-           if(composite!=null){
-               composite.getViewer().getControl().setFocus();
+           if(viewer!=null){
+               viewer.getControl().setFocus();
            }
         if(conversation!=null && !conversation.isBound()){
             conversation.bind();
@@ -152,23 +221,26 @@ public class FeatureTreeEditor implements ICdmEntitySessionEnabled,
 
        @Override
     public void refresh(){
-           composite.getViewer().refresh();
+           viewer.refresh();
        }
 
        public TreeViewer getViewer(){
-           return composite.getViewer();
+           return viewer;
        }
 
-       /**
-        * {@inheritDoc}
-        */
        @Override
        public IStructuredSelection getSelection() {
-           return (IStructuredSelection) composite.getViewer().getSelection();
+           return (IStructuredSelection) viewer.getSelection();
        }
 
-       @Persist
-       public void save(){
+       @Override
+       public ConversationHolder getConversationHolder() {
+           return conversation;
+       }
+
+       @Override
+    @Persist
+       public void save(IProgressMonitor monitor){
         if (!conversation.isBound()) {
             conversation.bind();
         }
@@ -176,19 +248,34 @@ public class FeatureTreeEditor implements ICdmEntitySessionEnabled,
         // commit the conversation and start a new transaction immediately
         conversation.commit(true);
 
-        CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(composite.getFeatureTree());
+        CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(getRootEntities());
+
+        List<FeatureTree> rootEntities = getRootEntities();
+        for (FeatureTree featureTree : rootEntities) {
+            if(featureTree.getTermType().equals(TermType.Character)){
+                FeatureTree<Character> characterTree = featureTree;
+                //save characters because they can be modified in this editor
+                characterTree.getDistinctFeatures().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
+            }
+        }
+
+        initializeTrees();
 
         this.setDirty(false);
        }
 
+    private void initializeTrees() {
+        Object[] expandedElements = viewer.getExpandedElements();
+        viewer.getTree().removeAll();
+        List<FeatureTree> trees = CdmStore.getService(IFeatureTreeService.class).list(FeatureTree.class, null, null, null, null);
+        viewer.setInput(trees);
+        viewer.setExpandedElements(expandedElements);
+    }
+
        @PreDestroy
        public void dispose(){
-        if(conversation!=null){
-            conversation.close();
-        }
-        if(cdmEntitySession != null) {
-            cdmEntitySession.dispose();
-        }
+           selService.setSelection(null);
+           clearSession();
        }
 
     @Override
@@ -209,14 +296,71 @@ public class FeatureTreeEditor implements ICdmEntitySessionEnabled,
         return propertyPathMap;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public List<FeatureTree> getRootEntities() {
-        List<FeatureTree> root = new ArrayList<>();
-        root.add(composite.getFeatureTree());
-        return root;
+        return (List<FeatureTree>) viewer.getInput();
+    }
+
+    @Override
+    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
+    }
+
+    @Override
+    public void contextStop(IMemento memento, IProgressMonitor monitor) {
+        //close view when workbench closes
+        try{
+            thisPart.getContext().get(EPartService.class).hidePart(thisPart);
+        }
+        catch(Exception e){
+            //nothing
+        }
+    }
+
+    @Override
+    public void contextStart(IMemento memento, IProgressMonitor monitor) {
+    }
+
+    @Override
+    public void contextRefresh(IProgressMonitor monitor) {
+    }
+
+    @Override
+    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
+    }
+
+    @Override
+    public void update(CdmDataChangeMap arg0) {
+    }
+
+    @Override
+    public void changed(Object element) {
+        dirty.setDirty(true);
+        viewer.refresh();
+    }
+
+    @Override
+    public void forceDirty() {
+        dirty.setDirty(true);
+    }
+
+    @Override
+    public boolean postOperation(Object objectAffectedByOperation) {
+        initializeTrees();
+        viewer.refresh();
+        if(objectAffectedByOperation instanceof FeatureNode){
+            FeatureNode node = (FeatureNode)objectAffectedByOperation;
+            viewer.expandToLevel(node.getFeatureTree(), 1);
+        }
+        if(objectAffectedByOperation!=null){
+            StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
+            viewer.setSelection(selection);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onComplete() {
+        return false;
     }
 
 }