Rename Derivative View to Derivative Editor
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / view / derivate / DerivateView.java
index 1d39782342dee9056ded110c1ff0c015a4baf0ec..a7845395ed1b783ac5bb80dc3a0cf5d933986ed5 100644 (file)
 package eu.etaxonomy.taxeditor.editor.view.derivate;
 
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
+
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.util.LocalSelectionTransfer;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
 import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeNode;
+import org.eclipse.jface.viewers.TreeSelection;
 import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.Tree;
-import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.part.EditorPart;
 
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.cdm.api.service.IOccurrenceService;
+import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
 import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.taxeditor.bulkeditor.BulkEditor;
-import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.cdm.model.molecular.Sequence;
+import eu.etaxonomy.cdm.model.molecular.SingleRead;
+import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
+import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
+import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
-import eu.etaxonomy.taxeditor.view.AbstractCdmEditorViewPart;
+import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
+import eu.etaxonomy.taxeditor.store.CdmStore;
+import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateContentProvider;
+import eu.etaxonomy.taxeditor.view.derivateSearch.DerivateLabelProvider;
 
 /**
- * Displays the derivate hierarchy of all derivates belonging to a taxon.
+ * Displays the derivate hierarchy of the specimen specified in the editor input.
  *
  */
-public class DerivateView extends AbstractCdmEditorViewPart implements IPartContentHasDetails, IPartContentHasSupplementalData {
+public class DerivateView extends EditorPart implements IPartContentHasFactualData, IDirtyMarkable,
+        IConversationEnabled, IPartContentHasDetails, IPartContentHasSupplementalData, IPartContentHasMedia,
+        ISelectionChangedListener, IPostOperationEnabled {
+
+    public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView";
+
+       private ConversationHolder conversation;
+
+       private TreeViewer viewer;
+
+    private boolean isDirty;
+
+    private final int dndOperations = DND.DROP_MOVE;
+
+    private DerivateLabelProvider labelProvider;
+
+    private Set<SingleRead> multiLinkSingleReads;
 
-       /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.view.desc"{trunked}</code> */
-       public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView";
+    private ISelection selection = null;
 
-       protected TreeViewer viewer;
+    /**
+     * Default constructor
+     */
+    public DerivateView() {
+    }
 
-       @Override
-       public void createViewer(Composite parent) {
-               viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
-               viewer.setContentProvider(new DerivateContentProvider());
-               viewer.setLabelProvider(new DerivateLabelProvider());
-               viewer.setAutoExpandLevel(2);
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
+     */
+    @Override
+    public void createPartControl(Composite parent) {
+        viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
+        viewer.setContentProvider(new DerivateContentProvider());
+        labelProvider = new DerivateLabelProvider();
+        labelProvider.setConversation(conversation);
+        viewer.setLabelProvider(labelProvider);
+        viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
         // Propagate selection from viewer
         getSite().setSelectionProvider(viewer);
+        //listen to selection changes
+        viewer.addSelectionChangedListener(this);
 
         //create context menu
         MenuManager menuManager = new MenuManager();
-
         getSite().registerContextMenu(menuManager, viewer);
-
         Control control = viewer.getControl();
         Menu menu = menuManager.createContextMenu(control);
-
         control.setMenu(menu);
-       }
 
-       @Override
-       public void selectionChanged(IWorkbenchPart part, ISelection selection) {
-           if(AbstractUtility.getActiveEditor()==null || !(AbstractUtility.getActiveEditor() instanceof BulkEditor)){
-               showEmptyPage();
-               return;
-           }
-           else if(part instanceof BulkEditor){
-               this.part = part;
+        generateMultiLinkSingleReads();
+        labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
+        IEditorInput editorInput = getEditorInput();
+        viewer.setInput(((DerivateViewEditorInput) editorInput).getRootUUIDs());
+        //set selection to selected derivate if only one was selected
+        if(editorInput instanceof DerivateViewEditorInput){
+            Set<UUID> derivateUUIDs = ((DerivateViewEditorInput) editorInput).getDerivateUUIDs();
+            if(derivateUUIDs.size()==1){
+                SpecimenOrObservationBase<?> specimen = CdmStore.getService(IOccurrenceService.class).load(derivateUUIDs.iterator().next());
+                if(specimen!=null){
+                    viewer.setSelection(new StructuredSelection(new TreeNode(specimen)));
+                }
+            }
+        }
+
+        //add drag'n'drop support
+        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
+        viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
+        viewer.addDropSupport(dndOperations, transfers, new DerivateDropListener(this));
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
+     */
+    @Override
+    public void doSave(IProgressMonitor monitor) {
+        String taskName = "Saving hierarchy";
+        if(getEditorInput() instanceof DerivateViewEditorInput){
+            DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
+            taskName += " "+derivateViewEditorInput.getName();
+        }
+        monitor.beginTask(taskName, 3);
+        if (!conversation.isBound()) {
+            conversation.bind();
+        }
+        monitor.worked(1);
+
+        // commit the conversation and start a new transaction immediately
+        conversation.commit(true);
+        monitor.worked(1);
+
+        this.setDirty(false);
+        monitor.worked(1);
+        monitor.done();
+        firePropertyChange(PROP_DIRTY);
+        refreshTree();
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#doSaveAs()
+     */
+    @Override
+    public void doSaveAs() {
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#getTitleToolTip()
+     */
+    @Override
+    public String getTitleToolTip() {
+        if(getEditorInput() instanceof DerivateViewEditorInput){
+            DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) getEditorInput();
+            return derivateViewEditorInput.getName();
+        }
+        return "Derivative Editor";
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
+     */
+    @Override
+    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+        setSite(site);
+        setInput(input);
+        if(input instanceof DerivateViewEditorInput){
+            DerivateViewEditorInput derivateViewEditorInput = (DerivateViewEditorInput) input;
+            conversation = derivateViewEditorInput.getConversationHolder();
+            setPartName(derivateViewEditorInput.getName());
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#isDirty()
+     */
+    @Override
+    public boolean isDirty() {
+        return isDirty;
+    }
+
+    /**
+     * @param isDirty the isDirty to set
+     */
+    public void setDirty(boolean isDirty) {
+        this.isDirty = isDirty;
+    }
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
+     */
+    @Override
+    public boolean isSaveAsAllowed() {
+        return false;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
+     */
+    @Override
+    public void setFocus() {
+        viewer.getControl().setFocus();
+        //make sure to bind again if maybe in another view the conversation was unbound
+        if(!conversation.isBound()){
+            conversation.bind();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
+     */
+    @Override
+    public void update(CdmDataChangeMap changeEvents) {
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
+     */
+    @Override
+    public ConversationHolder getConversationHolder() {
+        return conversation;
+    }
+
+    /**
+     * @return the viewer
+     */
+    public TreeViewer getViewer() {
+        return viewer;
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#changed(java.lang.Object)
+     */
+    @Override
+    public void changed(Object element) {
+        setDirty(true);
+        firePropertyChange(IEditorPart.PROP_DIRTY);
+        viewer.refresh();
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
+     */
+    @Override
+    public void forceDirty() {
+        changed(null);
+    }
+
+    /**
+     * Refreshes the derivate hierarchy tree and expands the tree
+     * to show and select the given object.
+     *
+     * @param expandTo the object to which the tree should be expanded
+     */
+    public void refreshTree(Object expandTo){
+        refreshTree();
+        TreeSelection selection = (TreeSelection) viewer.getSelection();
+        viewer.expandToLevel(selection.getFirstElement(), 1);
+        viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
+    }
+
+    /**
+     * Refreshes the derivate hierarchy tree
+     */
+    public void refreshTree(){
+        generateMultiLinkSingleReads();
+        labelProvider.setMultiLinkSingleReads(multiLinkSingleReads);
+        viewer.refresh();
+    }
+
 
-               getViewer().setInput(selection);
+    private void generateMultiLinkSingleReads() {
+        Set<SingleRead> multiLinkSingleReads = new HashSet<SingleRead>();
+        for(Entry<SingleRead, Collection<Sequence>> entry:CdmStore.getService(ISequenceService.class).getSingleReadSequencesMap().entrySet()){
+            if(entry.getValue().size()>1){
+                multiLinkSingleReads.add(entry.getKey());
+            }
+        }
+        this.multiLinkSingleReads = multiLinkSingleReads;
+    }
 
-               showViewer();
-               return;
-           }
-       }
+    /**
+     * @return a set of {@link SingleRead}s that have multiple parents
+     */
+    public Set<SingleRead> getMultiLinkSingleReads() {
+        return this.multiLinkSingleReads;
+    }
 
-       @Override
-       public boolean onComplete() {
-               // TODO Auto-generated method stub
-               return false;
-       }
+    /* (non-Javadoc)
+     * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+     */
+    @Override
+    public void selectionChanged(SelectionChangedEvent event) {
+        this.selection  = event.getSelection();
+    }
 
-       @Override
-       public Viewer getViewer() {
-               return viewer;
-       }
+    public ISelection getSelection() {
+        return selection;
+    }
 
+    public DerivateLabelProvider getLabelProvider() {
+        return labelProvider;
+    }
 
-       @Override
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.operation.IPostOperationEnabled#postOperation(eu.etaxonomy.cdm.model.common.CdmBase)
+     */
+    @Override
     public boolean postOperation(CdmBase objectAffectedByOperation) {
-               return super.postOperation(objectAffectedByOperation);
-       }
+        refreshTree();
+        if(objectAffectedByOperation!=null){
+            changed(objectAffectedByOperation);
+        }
+        return true;
+    }
 
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.operation.IPostOperationEnabled#onComplete()
+     */
+    @Override
+    public boolean onComplete() {
+        return true;
+    }
 
 }