ref #7086 Fix focus problem when saving
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / workingSet / WorkingSetEditor.java
index c899ff099fd35d56ccebb3767e3da420a3854849..9abb7bdded91ac918193b92c1fa145e56a005476 100644 (file)
 */
 package eu.etaxonomy.taxeditor.editor.workingSet;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
 import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
 
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
 import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.di.Persist;
+import org.eclipse.e4.ui.model.application.ui.MDirtyable;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.util.LocalSelectionTransfer;
+import org.eclipse.jface.viewers.IStructuredSelection;
+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.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
 
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.cdm.api.service.ITermService;
+import eu.etaxonomy.cdm.api.service.IWorkingSetService;
+import eu.etaxonomy.cdm.model.common.DefinedTermBase;
+import eu.etaxonomy.cdm.model.description.FeatureTree;
 import eu.etaxonomy.cdm.model.description.WorkingSet;
+import eu.etaxonomy.cdm.model.location.NamedArea;
+import eu.etaxonomy.cdm.model.name.Rank;
+import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.editor.l10n.Messages;
+import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
+import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
+import eu.etaxonomy.taxeditor.model.MessagingUtils;
+import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
+import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
+import eu.etaxonomy.taxeditor.store.CdmStore;
+import eu.etaxonomy.taxeditor.ui.dialog.selection.NamedAreaSelectionDialog;
 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
+import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
 
 /**
+ * Editor for configuring WorkingSets
  * @author pplitzner
  * @since Nov 21, 2017
  *
  */
-public class WorkingSetEditor {
+public class WorkingSetEditor implements IE4SavablePart, IConversationEnabled, ICdmEntitySessionEnabled,
+IPartContentHasDetails, IDirtyMarkable {
 
     private WorkingSetComposite composite;
 
+    private ConversationHolder conversation;
+
+    private ICdmEntitySession cdmEntitySession;
+
+    private WorkingSet workingSet;
+
+    private final int dndOperations = DND.DROP_MOVE;
+
+    @Inject
+    private MDirtyable dirty;
+
+    @Inject
+    private ESelectionService selectionService;
+
+    private ModifyListener labelModifyListener;
+
     @PostConstruct
-    public void create(Composite parent, IEclipseContext context){
+    public void create(Composite parent, IEclipseContext context, @Named(IServiceConstants.ACTIVE_SHELL)Shell shell){
+        if (CdmStore.isActive()){
+            if(conversation == null){
+                conversation = CdmStore.createConversation();
+            }
+            if(cdmEntitySession == null){
+                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
+            }
+        }
+        else{
+            return;
+        }
         CdmFormFactory cdmFormFactory = new CdmFormFactory(Display.getCurrent());
         ContextInjectionFactory.inject(cdmFormFactory, context);
+
         composite = new WorkingSetComposite(parent, SWT.NONE);
+
+        labelModifyListener = new ModifyListener() {
+            @Override
+            public void modifyText(ModifyEvent e) {
+                workingSet.setLabel(composite.getTxt_label().getText());
+                dirty.setDirty(true);
+            }
+        };
+        composite.getRankMin().addSelectionChangedListener(event->dirty.setDirty(true));
+        composite.getRankMax().addSelectionChangedListener(event->dirty.setDirty(true));
+
+        composite.getBtnChooseArea().addSelectionListener(new SelectionAdapter() {
+
+            @Override
+            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
+                NamedArea area = NamedAreaSelectionDialog.select(shell, null, null);
+                if(area!=null){
+                    composite.setArea(area);
+                }
+                dirty.setDirty(true);
+            }
+        });
+        composite.getBtnRemoveArea().addSelectionListener(new SelectionAdapter() {
+
+            @Override
+            public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
+                composite.removeArea();
+                dirty.setDirty(true);
+            }
+        });
+
+        composite.getFeatureTreeEditorComposite().init(null, null, e->selectionService.setSelection(e.getSelection()), null, null);
+
+        //add drag'n'drop support
+        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer()};
+        composite.getTaxonNodeTree().addDropSupport(dndOperations, transfers, new TaxonNodeDropAdapter(this));
+
+        composite.getTaxonNodeTree().getTree().addKeyListener(new KeyAdapter() {
+            @Override
+            public void keyPressed(KeyEvent e) {
+                if(e.character==SWT.DEL){
+                    IStructuredSelection selection = (IStructuredSelection) composite.getTaxonNodeTree().getSelection();
+                    if(selection.toList().stream().anyMatch(object->!(object instanceof TaxonNode))){
+                        MessagingUtils.warningDialog(Messages.WorkingSetEditor_DELETE_FAIL_TITLE, this.getClass(), Messages.WorkingSetEditor_DELETE_FAIL_MESSAGE);
+                        return;
+                    }
+                    Iterator<Object> iterator = selection.iterator();
+                    while(iterator.hasNext()){
+                        Object next = iterator.next();
+                        TaxonNode taxonNode = (TaxonNode) next;
+                        removeTaxonNode(taxonNode);
+                    }
+                }
+            }
+        });
+
+    }
+
+    public void init(UUID workingSetUuid) {
+        this.workingSet = CdmStore.getService(IWorkingSetService.class).load(workingSetUuid);
+        if(workingSet.getLabel()!=null){
+            composite.getTxt_label().setText(workingSet.getLabel());
+        }
+        if(workingSet.getDescriptiveSystem()!=null){
+            composite.setCharacters(workingSet.getDescriptiveSystem());
+        }
+        Rank maxRank = workingSet.getMaxRank();
+        if(maxRank!=null){
+            composite.setRankMax(maxRank);
+        }
+        Rank minRank = workingSet.getMinRank();
+        if(minRank!=null){
+            composite.setRankMin(minRank);
+        }
+        Set<NamedArea> geoFilter = workingSet.getGeoFilter();
+        if(geoFilter!=null && !geoFilter.isEmpty()){
+            composite.setArea(geoFilter.iterator().next());
+        }
+        Set<TaxonNode> taxonSubtreeFilter = workingSet.getTaxonSubtreeFilter();
+        if(taxonSubtreeFilter!=null){
+            composite.getTaxonNodeTree().setInput(taxonSubtreeFilter);
+        }
+
+        composite.getTxt_label().addModifyListener(labelModifyListener);
+    }
+
+    public void addTaxonNode(TaxonNode taxonNode){
+        //load into WS editor session
+        taxonNode = getCdmEntitySession().load(taxonNode, false);
+        Viewer taxonTreeViewer = getTaxonTreeViewer();
+        Object input = taxonTreeViewer.getInput();
+        Collection<TaxonNode> treeNodes;
+        if(input==null){
+            treeNodes = new ArrayList<>();
+        }
+        else{
+            treeNodes = (Collection<TaxonNode>) input;
+        }
+        treeNodes.add(taxonNode);
+        taxonTreeViewer.setInput(treeNodes);
+        dirty.setDirty(true);
+    }
+
+    private void removeTaxonNode(TaxonNode taxonNode){
+        Viewer taxonTreeViewer = getTaxonTreeViewer();
+        Collection<TaxonNode> input = (Collection<TaxonNode>) taxonTreeViewer.getInput();
+        input.remove(taxonNode);
+        workingSet.removeTaxonSubtree(taxonNode);
+        taxonTreeViewer.setInput(input);
+        dirty.setDirty(true);
+    }
+
+    @Persist
+    @Override
+    public void save(IProgressMonitor monitor) {
+        NamedArea area = composite.getArea();
+        Set<NamedArea> areas = new HashSet<>();
+        if(area!=null){
+            areas.add(area);
+        }
+        Object input = composite.getTaxonNodeTree().getInput();
+        if(input!=null){
+            workingSet.setTaxonSubtreeFilter(new HashSet<>());//clear existing filter
+            Collection<ITaxonTreeNode> taxonNodes = (Collection<ITaxonTreeNode>) input;
+            for (ITaxonTreeNode taxonTreeNode : taxonNodes) {
+                if(taxonTreeNode instanceof TaxonNode){
+                    TaxonNode taxonNode = (TaxonNode)taxonTreeNode;
+                    workingSet.addTaxonSubtree(taxonNode);
+                }
+            }
+        }
+        FeatureTree characters = composite.getCharacters();
+        if(characters!=null){
+            //save characters because they can be modified in this editor
+            characters.getDistinctFeatures().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
+        }
+
+
+        DefinedTermBase rankMaxSelection = composite.getRankMax().getSelection();
+        Rank rankMax = null;
+        if(rankMaxSelection instanceof Rank){
+            rankMax = (Rank) rankMaxSelection;
+        }
+        DefinedTermBase rankMinSelection = composite.getRankMin().getSelection();
+        Rank rankMin = null;
+        if(rankMinSelection instanceof Rank){
+            rankMin = (Rank) rankMinSelection;
+        }
+
+        workingSet.setMaxRank(rankMax);
+        workingSet.setMinRank(rankMin);
+        workingSet.setDescriptiveSystem(characters);
+        workingSet.setGeoFilter(areas);
+
+        conversation.commit();
+        CdmStore.getService(IWorkingSetService.class).merge(workingSet, true);
+
+        dirty.setDirty(false);
+    }
+
+    @PreDestroy
+    public void dispose() {
+        if (conversation != null) {
+            conversation.close();
+            conversation = null;
+        }
+        if(cdmEntitySession != null) {
+            cdmEntitySession.dispose();
+            cdmEntitySession = null;
+        }
+        dirty.setDirty(false);
+    }
+
+    @Focus
+    public void setFocus() {
+        if(composite!=null){
+            composite.setFocus();
+        }
+        if (getConversationHolder() != null) {
+            getConversationHolder().bind();
+        }
+        if(cdmEntitySession != null) {
+            cdmEntitySession.bind();
+        }
+    }
+
+    public Viewer getTaxonTreeViewer() {
+        return composite.getTaxonNodeTree();
+    }
+
+    public WorkingSet getWorkingSet() {
+        return workingSet;
+    }
+
+    @Override
+    public void update(CdmDataChangeMap arg0) {
+    }
+
+    @Override
+    public ICdmEntitySession getCdmEntitySession() {
+        return cdmEntitySession;
+    }
+
+    @Override
+    public Collection<WorkingSet> getRootEntities() {
+        return null;
+    }
+
+    @Override
+    public Map<Object, List<String>> getPropertyPathsMap() {
+        return null;
+    }
+
+    @Override
+    public ConversationHolder getConversationHolder() {
+        return conversation;
+    }
+
+    @Override
+    public void changed(Object element) {
+        dirty.setDirty(true);
     }
 
-    public void init(WorkingSet workingSet) {
-        composite.getTxt_label().setText(workingSet.getLabel());
+    @Override
+    public void forceDirty() {
+        dirty.setDirty(true);
     }
 
 }