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
.ISelectionProvider
;
25 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
26 import org
.eclipse
.swt
.SWT
;
27 import org
.eclipse
.swt
.dnd
.DND
;
28 import org
.eclipse
.swt
.dnd
.DropTarget
;
29 import org
.eclipse
.swt
.dnd
.Transfer
;
30 import org
.eclipse
.swt
.graphics
.Color
;
31 import org
.eclipse
.swt
.widgets
.Composite
;
32 import org
.eclipse
.swt
.widgets
.Display
;
33 import org
.eclipse
.swt
.widgets
.Menu
;
34 import org
.eclipse
.ui
.IEditorInput
;
35 import org
.eclipse
.ui
.IEditorSite
;
36 import org
.eclipse
.ui
.ISelectionListener
;
37 import org
.eclipse
.ui
.ISelectionService
;
38 import org
.eclipse
.ui
.IWorkbenchPart
;
39 import org
.eclipse
.ui
.IWorkbenchPartReference
;
40 import org
.eclipse
.ui
.PartInitException
;
41 import org
.eclipse
.ui
.forms
.ManagedForm
;
42 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
43 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
44 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
45 import org
.eclipse
.ui
.part
.EditorPart
;
47 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
48 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
49 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
50 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
51 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
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
.ContainerFactory
;
68 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.HomotypicalSynonymGroup
;
69 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.MisappliedGroup
;
70 import eu
.etaxonomy
.taxeditor
.editor
.name
.dnd
.NameEditorDropTargetListener
;
71 import eu
.etaxonomy
.taxeditor
.model
.IPartChangeListener
;
72 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasDetails
;
73 import eu
.etaxonomy
.taxeditor
.model
.TaxeditorPartService
;
74 import eu
.etaxonomy
.taxeditor
.operation
.IPostOperationEnabled
;
75 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
76 import eu
.etaxonomy
.taxeditor
.security
.RequiredPermissions
;
77 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
78 import eu
.etaxonomy
.taxeditor
.store
.StoreUtil
;
82 * TaxonNameEditor class.
90 public class TaxonNameEditor
extends EditorPart
implements
91 IMultiPageTaxonEditorPage
, IAdaptable
, IConversationEnabled
,
92 IPostOperationEnabled
, IPartContentHasDetails
, IPartChangeListener
,
93 ISelectionListener
, IDropTargetable
{
95 /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon.name"</code> */
96 public static final String ID
= "eu.etaxonomy.taxeditor.editor.taxon.name";
100 private ManagedForm managedForm
;
101 private ScrolledForm scrolledForm
;
102 private Composite parent
;
103 private ISelectionProvider simpleSelectionProvider
;
105 private final MultiPageTaxonEditor editor
;
107 private TaxonBase selection
;
109 private final ConversationHolder conversation
;
111 private MenuManager menuManager
;
114 private AcceptedGroup acceptedGroup
;
115 private List
<HomotypicalSynonymGroup
> heterotypicSynonymGroups
= new ArrayList
<HomotypicalSynonymGroup
>();
116 private MisappliedGroup misappliedGroup
;
118 private DropTarget target
;
120 private ISelectionService selectionService
;
122 private TaxonBase objectAffectedByLastOperation
;
126 * Constructor for TaxonNameEditor.
130 * a {@link eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor}
133 public TaxonNameEditor(MultiPageTaxonEditor editor
) {
134 this.editor
= editor
;
135 conversation
= editor
.getConversationHolder();
143 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
146 public IUndoContext
getUndoContext() {
147 return editor
.getUndoContext();
154 * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
159 public void createPartControl(Composite composite
) {
160 selectionService
= getSite().getWorkbenchWindow().getSelectionService();
161 selectionService
.addSelectionListener(this);
163 createManagedForm(composite
);
165 TaxeditorPartService
.getInstance().addListener(
166 TaxeditorPartService
.PART_ACTIVATED
, this);
175 * a {@link org.eclipse.swt.widgets.Composite} object.
177 protected void createManagedForm(Composite composite
) {
179 managedForm
= new ManagedForm(composite
) {
182 public void dirtyStateChanged() {
183 firePropertyChange(PROP_DIRTY
);
187 public boolean setInput(Object input
) {
188 if (input
instanceof AbstractGroupedContainer
) {
189 selection
= ((AbstractGroupedContainer
) input
).getData();
190 getSite().getSelectionProvider().setSelection(new StructuredSelection(selection
));
191 }else if(input
== null){
193 getSite().getSelectionProvider().setSelection(new StructuredSelection());
197 return super.setInput(input
);
201 scrolledForm
= managedForm
.getForm();
202 parent
= scrolledForm
.getBody();
204 // register the context menu
205 menuManager
= new MenuManager();
206 ISelectionProvider selectionProvider
= getSite().getSelectionProvider();
207 getSite().registerContextMenu(TaxonNameEditor
.ID
, menuManager
,
210 parent
.setData(taxon
);
212 TableWrapLayout layout
= new TableWrapLayout();
213 layout
.leftMargin
= 0;
214 layout
.rightMargin
= 0;
215 layout
.topMargin
= 0;
216 layout
.bottomMargin
= 0;
218 layout
.verticalSpacing
= 0;
219 layout
.horizontalSpacing
= 0;
221 parent
.setLayout(layout
);
222 parent
.setBackground(EditorUtil
223 .getColor(Resources
.COLOR_COMPOSITE_BACKGROUND
));
225 createOrUpdateNameComposites();
234 * createNameComposites
237 public void createOrUpdateNameComposites() {
239 ContainerFactory
.createOrUpdateAcceptedTaxonsHomotypicGroup(this);
240 ContainerFactory
.createOrUpdateHeterotypicSynonymyGroups(this);
241 ContainerFactory
.createOrUpdateMisapplicationsGroup(this);
244 managedForm
.reflow(true);
249 * Getter for the field <code>taxon</code>.
252 * @return a {@link eu.etaxonomy.cdm.model.taxon.Taxon} object.
254 public Taxon
getTaxon() {
255 return (Taxon
) HibernateProxyHelper
.deproxy(taxon
);
263 public void setDirty() {
264 managedForm
.dirtyStateChanged();
270 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
274 public void setFocus() {
275 if (getSelectedContainer() == null) {
276 throw new IllegalStateException(
277 "There should always be a selected object.");
279 getSelectedContainer().setSelected();
282 TaxonNode taxonNode
= ((TaxonEditorInput
)getEditorInput()).getTaxonNode();
283 boolean doEnable
= CdmStore
.currentAuthentiationHasPermission(taxonNode
, RequiredPermissions
.TAXONNODE_EDIT
);
291 public void setInput(IEditorInput input
) {
292 this.setInputWithNotify(input
);
299 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
304 * getConversationHolder
307 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
310 public ConversationHolder
getConversationHolder() {
318 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
319 * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
322 public void update(CdmDataChangeMap events
) {
327 * Redraws this editor return true on success
331 public boolean redraw() {
338 * Redraws the editor controls
340 public boolean redraw(boolean focus
) {
342 createOrUpdateNameComposites();
353 * getMultiPageTaxonEditor
356 * @return a {@link eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor}
359 public MultiPageTaxonEditor
getMultiPageTaxonEditor() {
367 * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
371 public boolean postOperation(CdmBase objectAffectedByOperation
) {
373 editor
.changed(objectAffectedByOperation
);
377 if (objectAffectedByOperation
instanceof TaxonBase
) {
378 objectAffectedByLastOperation
= (TaxonBase
) objectAffectedByOperation
;
386 * Getter for the field <code>managedForm</code>.
389 * @return the managedForm
391 public ManagedForm
getManagedForm() {
400 * @return a {@link org.eclipse.swt.widgets.Composite} object.
402 public Composite
getControl() {
403 return this.getManagedForm().getForm().getBody();
408 * Getter for the field <code>menu</code>.
413 public Menu
getMenu() {
414 if (menu
== null || menu
.isDisposed()) {
415 // Creating the menu because it was either not initialised or
416 // disposed while refreshing the editor
417 menu
= menuManager
.createContextMenu(parent
);
427 * @return true if there are empty names
429 public boolean checkForEmptyNames() {
430 for (AbstractGroupedContainer container
: getGroupedContainers()) {
431 if (container
.getName() == null
432 || StringUtils
.isEmpty(container
.getName().getTitleCache())) {
439 public Set
<AbstractGroupedContainer
> getEmptyContainers() {
440 Set
<AbstractGroupedContainer
> containersWithEmptyNames
= new HashSet
<AbstractGroupedContainer
>();
442 for (AbstractGroupedContainer container
: getGroupedContainers()) {
443 if (container
.getName() == null
444 || StringUtils
.isEmpty(container
.getName().getTitleCache())) {
445 containersWithEmptyNames
.add(container
);
449 return containersWithEmptyNames
;
454 public void doSave(IProgressMonitor monitor
) {
456 monitor
.beginTask("Saving names", getGroupedContainers().size());
459 // check for empty names
460 for (AbstractGroupedContainer container
: getGroupedContainers()) {
462 monitor
.subTask("Saving composite: "
463 + container
.getTaxonBase().getTitleCache());
464 container
.persistName();
466 // In case the progress monitor was canceled throw an exception.
467 if (monitor
.isCanceled()) {
468 throw new OperationCanceledException();
471 // Otherwise declare this step as done.
476 // Stop the progress monitor.
484 public void doSaveAs() {
489 public void init(IEditorSite site
, IEditorInput input
)
490 throws PartInitException
{
492 if (!(input
instanceof IEditorInput
))
493 throw new PartInitException("Invalid Input: Must be IEditorInput");
495 if (input
.getAdapter(Taxon
.class) != null) {
496 taxon
= (Taxon
) input
.getAdapter(Taxon
.class);
498 throw new PartInitException("Invalid Input: Taxon cannot be null");
504 simpleSelectionProvider
= new SimpleSelectionProvider();
505 getSite().setSelectionProvider(simpleSelectionProvider
);
512 private void createDragSupport() {
513 // Listen for names being dragged outside of existing homotypic groups -
514 // user wants to create a new group
515 Transfer
[] types
= new Transfer
[] { CdmDataTransfer
.getInstance() };
516 int operations
= DND
.DROP_MOVE
;
517 if (target
== null) {
518 target
= new DropTarget(parent
, operations
);
519 target
.setTransfer(types
);
520 target
.addDropListener(new NameEditorDropTargetListener(this));
526 * Getter for the field <code>acceptedNameContainer</code>.
530 * {@link eu.etaxonomy.taxeditor.editor.name.container.AcceptedNameContainer}
533 public AcceptedNameContainer
getAcceptedNameContainer() {
534 return getAcceptedGroup().getAcceptedNameContainer();
542 * @param homotypicalGroup
543 * a {@link eu.etaxonomy.cdm.model.name.HomotypicalGroup} object.
545 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
548 public HomotypicalSynonymGroup
getHomotypicalGroupContainer(
549 HomotypicalGroup homotypicalGroup
) {
550 for (HomotypicalSynonymGroup group
: getHeterotypicSynonymGroups()) {
551 if (group
.getGroup().equals(homotypicalGroup
)) {
564 * @return a Set containing all composites that have been edited
566 public Set
<AbstractGroupedContainer
> getDirtyNames() {
567 Set
<AbstractGroupedContainer
> dirtyNames
= new HashSet
<AbstractGroupedContainer
>();
569 for (AbstractGroupedContainer composite
: getGroupedContainers()) {
570 if (composite
.isDirty()) {
571 dirtyNames
.add(composite
);
580 * getGroupedContainers
583 * @return a {@link java.util.List} object.
585 public List
<AbstractGroupedContainer
> getGroupedContainers() {
586 List
<AbstractGroupedContainer
> groupedComposites
= new ArrayList
<AbstractGroupedContainer
>();
588 for (AbstractGroup group
: getAllGroups()) {
589 groupedComposites
.addAll(group
.getGroupedContainers());
592 return groupedComposites
;
600 * @return a {@link java.util.List} object.
602 public List
<AbstractGroup
> getAllGroups() {
603 List
<AbstractGroup
> allGroups
= new ArrayList
<AbstractGroup
>();
605 allGroups
.add(getAcceptedGroup());
607 // List<HomotypicalSynonymGroup> grps = getHeterotypicSynonymGroups(); // UNUSED => remove
609 heterotypicSynonymGroups
= getHeterotypicSynonymGroups();
611 if (heterotypicSynonymGroups
!= null) {
612 allGroups
.addAll(heterotypicSynonymGroups
);
615 if (misappliedGroup
!= null) {
616 allGroups
.add(misappliedGroup
);
625 * @see org.eclipse.ui.part.EditorPart#isDirty()
629 public boolean isDirty() {
630 return editor
.isDirty();
636 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
640 public void dispose() {
647 * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
651 public boolean isSaveAsAllowed() {
658 * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.
659 * IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
662 public void selectionChanged(IWorkbenchPart part
, ISelection selection
) {
671 * @return a {@link eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor}
674 public TaxonNameEditor
getEditor() {
680 * Getter for the field <code>selectedObject</code>.
684 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer}
687 public AbstractGroupedContainer
getSelectedContainer() {
689 TaxonBase selectedTaxonBase
= null;
691 TaxonEditorInput input
= (TaxonEditorInput
) editor
.getEditorInput();
692 if (input
.getInitiallySelectedTaxonBase() != null) {
693 selectedTaxonBase
= input
.getInitiallySelectedTaxonBase();
695 if (selection
!= null) {
696 selectedTaxonBase
= selection
;
700 return (selectedTaxonBase
!= null) ?
getContainer(selectedTaxonBase
)
701 : getAcceptedNameContainer();
709 public void dragEntered() {
711 getControl().setBackground(
712 EditorUtil
.getColor(Resources
.COLOR_DRAG_ENTER
));
720 public void dragLeft() {
721 getControl().setBackground(
722 EditorUtil
.getColor(Resources
.COLOR_COMPOSITE_BACKGROUND
));
728 * setMisapplicationsGroup
731 * @param misappliedGroup
733 * {@link eu.etaxonomy.taxeditor.editor.name.container.MisappliedGroup}
736 public void setMisapplicationsGroup(MisappliedGroup misappliedGroup
) {
737 this.misappliedGroup
= misappliedGroup
;
744 * eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage#isRedrawing()
753 public boolean isRedrawing() {
762 * @return a {@link org.eclipse.ui.forms.widgets.FormToolkit} object.
764 public FormToolkit
getToolkit() {
765 return managedForm
.getToolkit();
770 * getHeterotypicSynonymGroups
773 * @return a {@link java.util.List} object.
775 public List
<HomotypicalSynonymGroup
> getHeterotypicSynonymGroups() {
776 return heterotypicSynonymGroups
;
781 * addHeterotypicSynonymGroup
786 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
789 public void addHeterotypicSynonymGroup(HomotypicalSynonymGroup group
) {
790 heterotypicSynonymGroups
.add(group
);
795 * getHomotypicSynonymGroup
799 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
802 public AcceptedGroup
getAcceptedGroup() {
803 return acceptedGroup
;
808 * @param acceptedGroup
810 public void setAcceptedGroup(AcceptedGroup acceptedGroup
) {
811 this.acceptedGroup
= acceptedGroup
;
816 * Getter for the field <code>misappliedGroup</code>.
820 * {@link eu.etaxonomy.taxeditor.editor.name.container.MisappliedGroup}
823 public MisappliedGroup
getMisappliedGroup() {
824 return misappliedGroup
;
827 // TODO not very useful at the moment
835 public boolean isActive() {
836 IWorkbenchPart activePart
= EditorUtil
.getActivePart();
837 return editor
.equals(activePart
);
847 public boolean onComplete() {
848 getContainer(objectAffectedByLastOperation
).setSelected();
853 public void partChanged(Integer eventType
, IWorkbenchPartReference partRef
) {
854 if (!partRef
.getPart(false).equals(editor
)) {
855 // getSelectedObject().colorSelected(AbstractGroupedContainer.SELECTED_NO_FOCUS);
860 * @param retainedGroup
862 public void removeGroup(AbstractGroup group
) {
866 //if (heterotypicSynonymGroups != null) {
867 heterotypicSynonymGroups
.remove(group
);
876 public AbstractGroupedContainer
getContainer(TaxonBase taxonBase
) {
877 List
<AbstractGroupedContainer
> groupedContainers
= getGroupedContainers();
878 for (AbstractGroupedContainer container
: groupedContainers
) {
879 if (container
.getData().equals(taxonBase
)
880 && container
.getNameViewer().getTextWidget() != null) {
884 return getAcceptedNameContainer();
888 * @see eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage#setOnError()
890 public void setOnError() {
891 Color disabledColor
= StoreUtil
.getColor(Resources
.COLOR_EDITOR_ERROR
);
892 setDisabled(disabledColor
);
896 * @see eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage#setDisabled()
899 public void setDisabled(){
900 Color disabledColor
= StoreUtil
.getColor(Resources
.COLOR_TEXT_DISABLED_BACKGROUND
);
901 setDisabled(disabledColor
);
904 protected void setDisabled(Color disabledColor
) {
906 for(AbstractGroupedContainer groupedContainer
: getGroupedContainers()){
907 groupedContainer
.setDisabled(true);
910 // send an empty selection to the current provider - TODO only on error ???
911 getManagedForm().setInput(null);
913 for(AbstractGroupedContainer groupedContainer
: getGroupedContainers()){
914 groupedContainer
.setBackground(disabledColor
);
916 getControl().setBackground(disabledColor
);
920 public void setEnabled(boolean enabled
) {
921 //FIXME this method seems incomplete
922 for(AbstractGroupedContainer groupedContainer
: getGroupedContainers()){
923 groupedContainer
.setEnabled(getManagedForm().setInput(selection
));
926 // send an empty selection to the current provider
927 getManagedForm().setInput(null);