2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.taxeditor
.editor
.name
;
12 import java
.util
.ArrayList
;
13 import java
.util
.HashSet
;
14 import java
.util
.List
;
17 import org
.apache
.commons
.lang
.StringUtils
;
18 import org
.eclipse
.core
.commands
.operations
.IUndoContext
;
19 import org
.eclipse
.core
.runtime
.IAdaptable
;
20 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
21 import org
.eclipse
.core
.runtime
.OperationCanceledException
;
22 import org
.eclipse
.jface
.action
.MenuManager
;
23 import org
.eclipse
.jface
.viewers
.ISelection
;
24 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
25 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
26 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
27 import org
.eclipse
.swt
.SWT
;
28 import org
.eclipse
.swt
.dnd
.DND
;
29 import org
.eclipse
.swt
.dnd
.DropTarget
;
30 import org
.eclipse
.swt
.dnd
.Transfer
;
31 import org
.eclipse
.swt
.graphics
.Color
;
32 import org
.eclipse
.swt
.widgets
.Composite
;
33 import org
.eclipse
.swt
.widgets
.Display
;
34 import org
.eclipse
.swt
.widgets
.Menu
;
35 import org
.eclipse
.ui
.IEditorInput
;
36 import org
.eclipse
.ui
.IEditorSite
;
37 import org
.eclipse
.ui
.ISelectionListener
;
38 import org
.eclipse
.ui
.ISelectionService
;
39 import org
.eclipse
.ui
.IWorkbenchPart
;
40 import org
.eclipse
.ui
.IWorkbenchPartReference
;
41 import org
.eclipse
.ui
.PartInitException
;
42 import org
.eclipse
.ui
.forms
.ManagedForm
;
43 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
44 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
45 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
46 import org
.eclipse
.ui
.part
.EditorPart
;
48 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
49 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
50 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
51 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
52 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
55 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
56 import eu
.etaxonomy
.taxeditor
.editor
.CdmDataTransfer
;
57 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
58 import eu
.etaxonomy
.taxeditor
.editor
.IDropTargetable
;
59 import eu
.etaxonomy
.taxeditor
.editor
.IMultiPageTaxonEditorPage
;
60 import eu
.etaxonomy
.taxeditor
.editor
.MultiPageTaxonEditor
;
61 import eu
.etaxonomy
.taxeditor
.editor
.SimpleSelectionProvider
;
62 import eu
.etaxonomy
.taxeditor
.editor
.TaxonEditorInput
;
63 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AbstractGroup
;
64 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AbstractGroupedContainer
;
65 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AcceptedGroup
;
66 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AcceptedNameContainer
;
67 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.ConceptGroup
;
68 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.ContainerFactory
;
69 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.HomotypicalSynonymGroup
;
70 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.MisappliedGroup
;
71 import eu
.etaxonomy
.taxeditor
.editor
.name
.dnd
.NameEditorDropTargetListener
;
72 import eu
.etaxonomy
.taxeditor
.model
.IPartChangeListener
;
73 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasDetails
;
74 import eu
.etaxonomy
.taxeditor
.model
.TaxeditorPartService
;
75 import eu
.etaxonomy
.taxeditor
.operation
.IPostOperationEnabled
;
76 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
80 * TaxonNameEditor class.
88 public class TaxonNameEditor
extends EditorPart
implements
89 IMultiPageTaxonEditorPage
, IAdaptable
, IConversationEnabled
,
90 IPostOperationEnabled
, IPartContentHasDetails
, IPartChangeListener
,
91 ISelectionListener
, IDropTargetable
{
93 /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon.name"</code> */
94 public static final String ID
= "eu.etaxonomy.taxeditor.editor.taxon.name";
98 private ManagedForm managedForm
;
99 private ScrolledForm scrolledForm
;
100 private Composite parent
;
101 private ISelectionProvider selectionProvider
;
103 private final MultiPageTaxonEditor editor
;
105 private TaxonBase selection
;
107 private final ConversationHolder conversation
;
109 private MenuManager menuManager
;
113 private MisappliedGroup misappliedGroup
;
115 private ConceptGroup conceptGroup
;
117 private final List
<HomotypicalSynonymGroup
> heterotypicSynonymGroups
= new ArrayList
<HomotypicalSynonymGroup
>();
119 private DropTarget target
;
121 private ISelectionService selectionService
;
123 private AcceptedGroup acceptedGroup
;
125 private TaxonBase objectAffectedByLastOperation
;
129 * Constructor for TaxonNameEditor.
133 * a {@link eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor}
136 public TaxonNameEditor(MultiPageTaxonEditor editor
) {
137 this.editor
= editor
;
138 conversation
= editor
.getConversationHolder();
146 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
149 public IUndoContext
getUndoContext() {
150 return editor
.getUndoContext();
157 * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
162 public void createPartControl(Composite composite
) {
163 selectionService
= getSite().getWorkbenchWindow().getSelectionService();
164 selectionService
.addSelectionListener(this);
166 createManagedForm(composite
);
168 TaxeditorPartService
.getInstance().addListener(
169 TaxeditorPartService
.PART_ACTIVATED
, this);
178 * a {@link org.eclipse.swt.widgets.Composite} object.
180 protected void createManagedForm(Composite composite
) {
182 managedForm
= new ManagedForm(composite
) {
185 public void dirtyStateChanged() {
186 firePropertyChange(PROP_DIRTY
);
190 public boolean setInput(Object input
) {
191 if (input
instanceof AbstractGroupedContainer
) {
192 selection
= ((AbstractGroupedContainer
) input
).getData();
193 getSite().getSelectionProvider().setSelection(new StructuredSelection(selection
));
195 return super.setInput(input
);
199 scrolledForm
= managedForm
.getForm();
200 parent
= scrolledForm
.getBody();
202 // register the context menu
203 menuManager
= new MenuManager();
204 ISelectionProvider selectionProvider
= getSite().getSelectionProvider();
205 getSite().registerContextMenu(TaxonNameEditor
.ID
, menuManager
,
208 parent
.setData(taxon
);
210 TableWrapLayout layout
= new TableWrapLayout();
211 layout
.leftMargin
= 0;
212 layout
.rightMargin
= 0;
213 layout
.topMargin
= 0;
214 layout
.bottomMargin
= 0;
216 layout
.verticalSpacing
= 0;
217 layout
.horizontalSpacing
= 0;
219 parent
.setLayout(layout
);
220 parent
.setBackground(EditorUtil
221 .getColor(Resources
.COLOR_COMPOSITE_BACKGROUND
));
223 createOrUpdateNameComposites();
232 * createNameComposites
235 public void createOrUpdateNameComposites() {
237 ContainerFactory
.createOrUpdateAcceptedTaxonsHomotypicGroup(this);
238 ContainerFactory
.createOrUpdateHeterotypicSynonymyGroups(this);
239 ContainerFactory
.createOrUpdateMisapplicationsGroup(this);
240 ContainerFactory
.createOrUpdateConceptGroup(this);
243 managedForm
.reflow(true);
248 * Getter for the field <code>taxon</code>.
251 * @return a {@link eu.etaxonomy.cdm.model.taxon.Taxon} object.
253 public Taxon
getTaxon() {
254 return (Taxon
) HibernateProxyHelper
.deproxy(taxon
);
262 public void setDirty() {
263 managedForm
.dirtyStateChanged();
269 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
273 public void setFocus() {
274 if (getSelectedContainer() == null) {
275 throw new IllegalStateException(
276 "There should always be a selected object.");
278 getSelectedContainer().setSelected();
283 public void setInput(IEditorInput input
) {
284 this.setInputWithNotify(input
);
291 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
296 * getConversationHolder
299 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
302 public ConversationHolder
getConversationHolder() {
310 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
311 * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
314 public void update(CdmDataChangeMap events
) {
319 * Redraws this editor return true on success
323 public boolean redraw() {
330 * Redraws the editor controls
332 public boolean redraw(boolean focus
) {
334 createOrUpdateNameComposites();
345 * getMultiPageTaxonEditor
348 * @return a {@link eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor}
351 public MultiPageTaxonEditor
getMultiPageTaxonEditor() {
359 * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
363 public boolean postOperation(CdmBase objectAffectedByOperation
) {
365 editor
.changed(objectAffectedByOperation
);
369 if (objectAffectedByOperation
instanceof TaxonBase
) {
370 objectAffectedByLastOperation
= (TaxonBase
) objectAffectedByOperation
;
378 * Getter for the field <code>managedForm</code>.
381 * @return the managedForm
383 public ManagedForm
getManagedForm() {
392 * @return a {@link org.eclipse.swt.widgets.Composite} object.
394 public Composite
getControl() {
395 return this.getManagedForm().getForm().getBody();
400 * Getter for the field <code>menu</code>.
405 public Menu
getMenu() {
406 if (menu
== null || menu
.isDisposed()) {
407 // Creating the menu because it was either not initialised or
408 // disposed while refreshing the editor
409 menu
= menuManager
.createContextMenu(parent
);
419 * @return true if there are empty names
421 public boolean checkForEmptyNames() {
422 for (AbstractGroupedContainer container
: getGroupedContainers()) {
423 if (container
.getName() == null
424 || StringUtils
.isEmpty(container
.getName().getTitleCache())) {
431 public Set
<AbstractGroupedContainer
> getEmptyContainers() {
432 Set
<AbstractGroupedContainer
> containersWithEmptyNames
= new HashSet
<AbstractGroupedContainer
>();
434 for (AbstractGroupedContainer container
: getGroupedContainers()) {
435 if (container
.getName() == null
436 || StringUtils
.isEmpty(container
.getName().getTitleCache())) {
437 containersWithEmptyNames
.add(container
);
441 return containersWithEmptyNames
;
446 public void doSave(IProgressMonitor monitor
) {
448 monitor
.beginTask("Saving names", getGroupedContainers().size());
451 // check for empty names
452 for (AbstractGroupedContainer container
: getGroupedContainers()) {
454 monitor
.subTask("Saving composite: "
455 + container
.getTaxonBase().getTitleCache());
456 container
.persistName();
458 // In case the progress monitor was canceled throw an exception.
459 if (monitor
.isCanceled()) {
460 throw new OperationCanceledException();
463 // Otherwise declare this step as done.
468 // Stop the progress monitor.
476 public void doSaveAs() {
481 public void init(IEditorSite site
, IEditorInput input
)
482 throws PartInitException
{
484 if (!(input
instanceof IEditorInput
))
485 throw new PartInitException("Invalid Input: Must be IEditorInput");
487 if (input
.getAdapter(Taxon
.class) != null) {
488 taxon
= (Taxon
) input
.getAdapter(Taxon
.class);
490 throw new PartInitException("Invalid Input: Taxon cannot be null");
496 selectionProvider
= new SimpleSelectionProvider();
497 getSite().setSelectionProvider(selectionProvider
);
503 private void createDragSupport() {
504 // Listen for names being dragged outside of existing homotypic groups -
505 // user wants to create a new group
506 Transfer
[] types
= new Transfer
[] { CdmDataTransfer
.getInstance() };
507 int operations
= DND
.DROP_MOVE
;
508 if (target
== null) {
509 target
= new DropTarget(parent
, operations
);
510 target
.setTransfer(types
);
511 target
.addDropListener(new NameEditorDropTargetListener(this));
517 * Getter for the field <code>acceptedNameContainer</code>.
521 * {@link eu.etaxonomy.taxeditor.editor.name.container.AcceptedNameContainer}
524 public AcceptedNameContainer
getAcceptedNameContainer() {
525 return getAcceptedGroup().getAcceptedNameContainer();
533 * @param homotypicalGroup
534 * a {@link eu.etaxonomy.cdm.model.name.HomotypicalGroup} object.
536 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
539 public HomotypicalSynonymGroup
getHomotypicalGroupContainer(
540 HomotypicalGroup homotypicalGroup
) {
541 for (HomotypicalSynonymGroup group
: getHeterotypicSynonymGroups()) {
542 if (group
.getGroup().equals(homotypicalGroup
)) {
552 * Getter for the field <code>conceptGroup</code>.
556 * {@link eu.etaxonomy.taxeditor.editor.name.container.ConceptGroup}
559 public ConceptGroup
getConceptGroup() {
568 * @return a Set containing all composites that have been edited
570 public Set
<AbstractGroupedContainer
> getDirtyNames() {
571 Set
<AbstractGroupedContainer
> dirtyNames
= new HashSet
<AbstractGroupedContainer
>();
573 for (AbstractGroupedContainer composite
: getGroupedContainers()) {
574 if (composite
.isDirty()) {
575 dirtyNames
.add(composite
);
584 * getGroupedContainers
587 * @return a {@link java.util.List} object.
589 public List
<AbstractGroupedContainer
> getGroupedContainers() {
590 List
<AbstractGroupedContainer
> groupedComposites
= new ArrayList
<AbstractGroupedContainer
>();
592 for (AbstractGroup group
: getAllGroups()) {
593 groupedComposites
.addAll(group
.getGroupedContainers());
596 return groupedComposites
;
604 * @return a {@link java.util.List} object.
606 public List
<AbstractGroup
> getAllGroups() {
607 List
<AbstractGroup
> allGroups
= new ArrayList
<AbstractGroup
>();
609 allGroups
.add(getAcceptedGroup());
611 allGroups
.addAll(getHeterotypicSynonymGroups());
613 if (misappliedGroup
!= null) {
614 allGroups
.add(misappliedGroup
);
617 if (conceptGroup
!= null) {
618 allGroups
.add(conceptGroup
);
627 * @see org.eclipse.ui.part.EditorPart#isDirty()
631 public boolean isDirty() {
632 return editor
.isDirty();
638 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
642 public void dispose() {
649 * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
653 public boolean isSaveAsAllowed() {
660 * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.
661 * IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
664 public void selectionChanged(IWorkbenchPart part
, ISelection selection
) {
673 * @return a {@link eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor}
676 public TaxonNameEditor
getEditor() {
682 * Getter for the field <code>selectedObject</code>.
686 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer}
689 public AbstractGroupedContainer
getSelectedContainer() {
691 TaxonBase selectedTaxonBase
= null;
693 TaxonEditorInput input
= (TaxonEditorInput
) editor
.getEditorInput();
694 if (input
.getInitiallySelectedTaxonBase() != null) {
695 selectedTaxonBase
= input
.getInitiallySelectedTaxonBase();
697 if (selection
!= null) {
698 selectedTaxonBase
= selection
;
702 return (selectedTaxonBase
!= null) ?
getContainer(selectedTaxonBase
)
703 : getAcceptedNameContainer();
711 public void dragEntered() {
713 getControl().setBackground(
714 EditorUtil
.getColor(Resources
.COLOR_DRAG_ENTER
));
722 public void dragLeft() {
723 getControl().setBackground(
724 EditorUtil
.getColor(Resources
.COLOR_COMPOSITE_BACKGROUND
));
729 * Setter for the field <code>conceptGroup</code>.
732 * @param conceptGroup
734 * {@link eu.etaxonomy.taxeditor.editor.name.container.ConceptGroup}
737 public void setConceptGroup(ConceptGroup conceptGroup
) {
738 this.conceptGroup
= conceptGroup
;
743 * setMisapplicationsGroup
746 * @param misappliedGroup
748 * {@link eu.etaxonomy.taxeditor.editor.name.container.MisappliedGroup}
751 public void setMisapplicationsGroup(MisappliedGroup misappliedGroup
) {
752 this.misappliedGroup
= misappliedGroup
;
759 * eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage#isRedrawing()
768 public boolean isRedrawing() {
777 * @return a {@link org.eclipse.ui.forms.widgets.FormToolkit} object.
779 public FormToolkit
getToolkit() {
780 return managedForm
.getToolkit();
785 * getHeterotypicSynonymGroups
788 * @return a {@link java.util.List} object.
790 public List
<HomotypicalSynonymGroup
> getHeterotypicSynonymGroups() {
791 return heterotypicSynonymGroups
;
796 * addHeterotypicSynonymGroup
801 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
804 public void addHeterotypicSynonymGroup(HomotypicalSynonymGroup group
) {
805 heterotypicSynonymGroups
.add(group
);
810 * getHomotypicSynonymGroup
814 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
817 public AcceptedGroup
getAcceptedGroup() {
818 return acceptedGroup
;
823 * @param acceptedGroup
825 public void setAcceptedGroup(AcceptedGroup acceptedGroup
) {
826 this.acceptedGroup
= acceptedGroup
;
831 * Getter for the field <code>misappliedGroup</code>.
835 * {@link eu.etaxonomy.taxeditor.editor.name.container.MisappliedGroup}
838 public MisappliedGroup
getMisappliedGroup() {
839 return misappliedGroup
;
842 // TODO not very useful at the moment
850 public boolean isActive() {
851 IWorkbenchPart activePart
= EditorUtil
.getActivePart();
852 return editor
.equals(activePart
);
862 public boolean onComplete() {
863 getContainer(objectAffectedByLastOperation
).setSelected();
868 public void partChanged(Integer eventType
, IWorkbenchPartReference partRef
) {
869 if (!partRef
.getPart(false).equals(editor
)) {
870 // getSelectedObject().colorSelected(AbstractGroupedContainer.SELECTED_NO_FOCUS);
875 * @param retainedGroup
877 public void removeGroup(AbstractGroup group
) {
880 getHeterotypicSynonymGroups().remove(group
);
888 public AbstractGroupedContainer
getContainer(TaxonBase taxonBase
) {
889 List
<AbstractGroupedContainer
> groupedContainers
= getGroupedContainers();
890 for (AbstractGroupedContainer container
: groupedContainers
) {
891 if (container
.getData().equals(taxonBase
)
892 && container
.getNameViewer().getTextWidget() != null) {
896 return getAcceptedNameContainer();
900 public void setDisabled(){
903 // coloring the widgets
905 // TODO move this to resources and make configurable via Preferences
906 Color disabledColor
= Display
.getDefault().getSystemColor(SWT
.COLOR_RED
);
908 for(AbstractGroupedContainer groupedContainer
: getGroupedContainers()){
909 groupedContainer
.setBackground(disabledColor
);
911 getControl().setBackground(disabledColor
);
915 public void setEnabled(boolean enabled
) {
916 for(AbstractGroupedContainer groupedContainer
: getGroupedContainers()){
917 groupedContainer
.setEnabled(getManagedForm().setInput(selection
));
920 // send an empty selection to the current provider
921 selectionProvider
.setSelection(new StructuredSelection());
923 // decide on the new selection provider
925 ISelectionProvider newSelectionProvider
= enabled ? selectionProvider
: new ISelectionProvider() {
928 public void setSelection(ISelection selection
) {
933 public void removeSelectionChangedListener(
934 ISelectionChangedListener listener
) {
939 public ISelection
getSelection() {
944 public void addSelectionChangedListener(ISelectionChangedListener listener
) {
949 getSite().setSelectionProvider(newSelectionProvider
);
951 System
.out
.println("SELECTION PROVIDER" + getSite().getSelectionProvider());