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
.IProgressMonitor
;
20 import org
.eclipse
.core
.runtime
.OperationCanceledException
;
21 import org
.eclipse
.jface
.action
.MenuManager
;
22 import org
.eclipse
.jface
.viewers
.ISelection
;
23 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
24 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
25 import org
.eclipse
.swt
.dnd
.DND
;
26 import org
.eclipse
.swt
.dnd
.DropTarget
;
27 import org
.eclipse
.swt
.dnd
.Transfer
;
28 import org
.eclipse
.swt
.graphics
.Color
;
29 import org
.eclipse
.swt
.widgets
.Composite
;
30 import org
.eclipse
.swt
.widgets
.Menu
;
31 import org
.eclipse
.ui
.IEditorInput
;
32 import org
.eclipse
.ui
.IEditorSite
;
33 import org
.eclipse
.ui
.ISelectionListener
;
34 import org
.eclipse
.ui
.ISelectionService
;
35 import org
.eclipse
.ui
.IWorkbenchPart
;
36 import org
.eclipse
.ui
.IWorkbenchPartReference
;
37 import org
.eclipse
.ui
.PartInitException
;
38 import org
.eclipse
.ui
.PlatformUI
;
39 import org
.eclipse
.ui
.forms
.ManagedForm
;
40 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
41 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
42 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
43 import org
.eclipse
.ui
.part
.EditorPart
;
45 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
46 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
47 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
48 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
49 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
51 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
53 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
54 import eu
.etaxonomy
.taxeditor
.editor
.CdmDataTransfer
;
55 import eu
.etaxonomy
.taxeditor
.editor
.IDropTargetable
;
56 import eu
.etaxonomy
.taxeditor
.editor
.IMultiPageTaxonEditorPage
;
57 import eu
.etaxonomy
.taxeditor
.editor
.ISecuredEditor
;
58 import eu
.etaxonomy
.taxeditor
.editor
.MultiPageTaxonEditor
;
59 import eu
.etaxonomy
.taxeditor
.editor
.SimpleSelectionProvider
;
60 import eu
.etaxonomy
.taxeditor
.editor
.TaxonEditorInput
;
61 import eu
.etaxonomy
.taxeditor
.editor
.l10n
.Messages
;
62 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AbstractGroup
;
63 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AbstractGroupedContainer
;
64 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AcceptedGroup
;
65 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AcceptedNameContainer
;
66 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.ContainerFactory
;
67 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.HomotypicalSynonymGroup
;
68 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.MisappliedGroup
;
69 import eu
.etaxonomy
.taxeditor
.editor
.name
.dnd
.NameEditorDropTargetListener
;
70 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
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
.preference
.Resources
;
75 import eu
.etaxonomy
.taxeditor
.security
.RequiredPermissions
;
76 import eu
.etaxonomy
.taxeditor
.session
.ICdmEntitySession
;
77 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
81 * TaxonNameEditor class.
89 public class TaxonNameEditor
extends EditorPart
implements
90 IMultiPageTaxonEditorPage
, IConversationEnabled
,
91 IPartContentHasDetails
, IPartChangeListener
,
92 ISelectionListener
, IDropTargetable
, ISecuredEditor
{
94 /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon.name"</code> */
95 public static final String ID
= "eu.etaxonomy.taxeditor.editor.taxon.name"; //$NON-NLS-1$
99 private ManagedForm managedForm
;
100 private ScrolledForm scrolledForm
;
101 private Composite parent
;
102 private ISelectionProvider simpleSelectionProvider
;
104 private final MultiPageTaxonEditor editor
;
106 private TaxonBase selection
;
108 private final ConversationHolder conversation
;
110 private MenuManager menuManager
;
113 private AcceptedGroup acceptedGroup
;
114 private List
<HomotypicalSynonymGroup
> heterotypicSynonymGroups
= new ArrayList
<HomotypicalSynonymGroup
>();
115 private MisappliedGroup misappliedGroup
;
117 private DropTarget target
;
119 private ISelectionService selectionService
;
121 private TaxonBase objectAffectedByLastOperation
;
123 private ICdmEntitySession cdmEntitySession
;
127 * Constructor for TaxonNameEditor.
131 * a {@link eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor}
134 public TaxonNameEditor(MultiPageTaxonEditor editor
) {
135 this.editor
= editor
;
136 conversation
= editor
.getConversationHolder();
144 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
147 public IUndoContext
getUndoContext() {
148 return editor
.getUndoContext();
155 * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
160 public void createPartControl(Composite composite
) {
161 selectionService
= getSite().getWorkbenchWindow().getSelectionService();
162 selectionService
.addSelectionListener(this);
164 createManagedForm(composite
);
166 TaxeditorPartService
.getInstance().addListener(
167 TaxeditorPartService
.PART_ACTIVATED
, this);
176 * a {@link org.eclipse.swt.widgets.Composite} object.
178 protected void createManagedForm(Composite composite
) {
180 managedForm
= new ManagedForm(composite
) {
183 public void dirtyStateChanged() {
184 firePropertyChange(PROP_DIRTY
);
188 public boolean setInput(Object input
) {
189 if (input
instanceof AbstractGroupedContainer
) {
190 selection
= ((AbstractGroupedContainer
) input
).getData();
191 getSite().getSelectionProvider().setSelection(new StructuredSelection(selection
));
192 }else if(input
== null){
194 getSite().getSelectionProvider().setSelection(new StructuredSelection());
198 return super.setInput(input
);
202 scrolledForm
= managedForm
.getForm();
203 parent
= scrolledForm
.getBody();
205 // register the context menu
206 menuManager
= new MenuManager();
207 ISelectionProvider selectionProvider
= getSite().getSelectionProvider();
208 getSite().registerContextMenu(TaxonNameEditor
.ID
, menuManager
,
210 menuManager
.setRemoveAllWhenShown(true);
212 parent
.setData(taxon
);
214 TableWrapLayout layout
= new TableWrapLayout();
215 layout
.leftMargin
= 0;
216 layout
.rightMargin
= 0;
217 layout
.topMargin
= 0;
218 layout
.bottomMargin
= 0;
220 layout
.verticalSpacing
= 0;
221 layout
.horizontalSpacing
= 0;
223 parent
.setLayout(layout
);
224 parent
.setBackground(AbstractUtility
225 .getColor(Resources
.COLOR_COMPOSITE_BACKGROUND
));
227 createOrUpdateNameComposites();
236 * createNameComposites
239 public void createOrUpdateNameComposites() {
240 // this.taxon = (Taxon)CdmStore.getService(ITaxonService.class).load(this.getTaxon().getUuid());
241 ContainerFactory
.createOrUpdateAcceptedTaxonsHomotypicGroup(this);
242 ContainerFactory
.createOrUpdateHeterotypicSynonymyGroups(this);
243 ContainerFactory
.createOrUpdateMisapplicationsGroup(this);
247 managedForm
.reflow(true);
252 * Getter for the field <code>taxon</code>.
255 * @return a {@link eu.etaxonomy.cdm.model.taxon.Taxon} object.
257 public Taxon
getTaxon() {
258 return HibernateProxyHelper
.deproxy(taxon
);
266 public void setDirty() {
267 managedForm
.dirtyStateChanged();
273 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
277 public void setFocus() {
278 PlatformUI
.getWorkbench().getActiveWorkbenchWindow().getShell().setFocus();
279 if (getSelectedContainer() == null) {
280 throw new IllegalStateException(
281 Messages
.TaxonNameEditor_THERE_SHOULD_ALWAYS_BE
);
283 getSelectedContainer().setSelected();
286 boolean doEnable
= permissionsSatisfied();
287 setEnabled(doEnable
);
291 * @see eu.etaxonomy.taxeditor.editor.name.ISecuredEditorPart#permissionsSatisfied()
294 public boolean permissionsSatisfied() {
295 TaxonNode taxonNode
= ((TaxonEditorInput
)getEditorInput()).getTaxonNode();
296 boolean doEnable
= CdmStore
.currentAuthentiationHasPermission(taxonNode
, RequiredPermissions
.TAXONNODE_EDIT
);
302 public void setInput(IEditorInput input
) {
303 this.setInputWithNotify(input
);
310 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
315 * getConversationHolder
318 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
322 public ConversationHolder
getConversationHolder() {
330 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
331 * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
335 public void update(CdmDataChangeMap events
) {
340 * Redraws this editor return true on success
345 public boolean redraw() {
352 * Redraws the editor controls
355 public boolean redraw(boolean focus
) {
357 createOrUpdateNameComposites();
368 * getMultiPageTaxonEditor
371 * @return a {@link eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor}
374 public MultiPageTaxonEditor
getMultiPageTaxonEditor() {
382 * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
387 public boolean postOperation(CdmBase objectAffectedByOperation
) {
389 editor
.changed(objectAffectedByOperation
);
393 if (objectAffectedByOperation
instanceof TaxonBase
) {
394 objectAffectedByLastOperation
= (TaxonBase
) objectAffectedByOperation
;
402 * Getter for the field <code>managedForm</code>.
405 * @return the managedForm
407 public ManagedForm
getManagedForm() {
416 * @return a {@link org.eclipse.swt.widgets.Composite} object.
419 public Composite
getControl() {
420 return this.getManagedForm().getForm().getBody();
425 * Getter for the field <code>menu</code>.
430 public Menu
getMenu() {
431 if (menu
== null || menu
.isDisposed()) {
432 // Creating the menu because it was either not initialised or
433 // disposed while refreshing the editor
434 menu
= menuManager
.createContextMenu(parent
);
444 * @return true if there are empty names
446 public boolean checkForEmptyNames() {
447 for (AbstractGroupedContainer container
: getGroupedContainers()) {
448 if (container
.getName() == null
449 || StringUtils
.isEmpty(container
.getName().getTitleCache())) {
456 public Set
<AbstractGroupedContainer
> getEmptyContainers() {
457 Set
<AbstractGroupedContainer
> containersWithEmptyNames
= new HashSet
<AbstractGroupedContainer
>();
459 for (AbstractGroupedContainer container
: getGroupedContainers()) {
460 if (container
.getName() == null
461 || StringUtils
.isEmpty(container
.getName().getTitleCache())) {
462 containersWithEmptyNames
.add(container
);
466 return containersWithEmptyNames
;
471 public void doSave(IProgressMonitor monitor
) {
473 monitor
.beginTask(Messages
.TaxonNameEditor_SAVING_NAMES
, getGroupedContainers().size());
476 // check for empty names
477 for (AbstractGroupedContainer container
: getGroupedContainers()) {
479 monitor
.subTask(Messages
.TaxonNameEditor_SAVING_COMPOSITES
480 + container
.getTaxonBase().getTitleCache());
481 container
.persistName();
483 // In case the progress monitor was canceled throw an exception.
484 if (monitor
.isCanceled()) {
485 throw new OperationCanceledException();
488 // Otherwise declare this step as done.
493 // Stop the progress monitor.
501 public void doSaveAs() {
506 public void init(IEditorSite site
, IEditorInput input
)
507 throws PartInitException
{
509 if (!(input
!= null)) {
510 throw new PartInitException(Messages
.TaxonNameEditor_INVALID_INPUT
);
513 if (input
.getAdapter(Taxon
.class) != null) {
514 taxon
= CdmBase
.deproxy(input
.getAdapter(Taxon
.class), Taxon
.class);
516 throw new PartInitException(Messages
.TaxonNameEditor_INVALID_INPUT_TAXON_NULL
);
522 simpleSelectionProvider
= new SimpleSelectionProvider();
523 getSite().setSelectionProvider(simpleSelectionProvider
);
530 private void createDragSupport() {
531 // Listen for names being dragged outside of existing homotypic groups -
532 // user wants to create a new group
533 Transfer
[] types
= new Transfer
[] { CdmDataTransfer
.getInstance() };
534 int operations
= DND
.DROP_MOVE
;
535 if (target
== null) {
536 target
= new DropTarget(parent
, operations
);
537 target
.setTransfer(types
);
538 target
.addDropListener(new NameEditorDropTargetListener(this));
544 * Getter for the field <code>acceptedNameContainer</code>.
548 * {@link eu.etaxonomy.taxeditor.editor.name.container.AcceptedNameContainer}
551 public AcceptedNameContainer
getAcceptedNameContainer() {
552 return getAcceptedGroup().getAcceptedNameContainer();
560 * @param homotypicalGroup
561 * a {@link eu.etaxonomy.cdm.model.name.HomotypicalGroup} object.
563 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
566 public HomotypicalSynonymGroup
getHomotypicalGroupContainer(
567 HomotypicalGroup homotypicalGroup
) {
568 for (HomotypicalSynonymGroup group
: getHeterotypicSynonymGroups()) {
569 if (group
.getGroup().equals(homotypicalGroup
)) {
582 * @return a Set containing all composites that have been edited
584 public Set
<AbstractGroupedContainer
> getDirtyNames() {
585 Set
<AbstractGroupedContainer
> dirtyNames
= new HashSet
<AbstractGroupedContainer
>();
587 for (AbstractGroupedContainer composite
: getGroupedContainers()) {
588 if (composite
.isDirty()) {
589 dirtyNames
.add(composite
);
598 * getGroupedContainers
601 * @return a {@link java.util.List} object.
603 public List
<AbstractGroupedContainer
> getGroupedContainers() {
604 List
<AbstractGroupedContainer
> groupedComposites
= new ArrayList
<AbstractGroupedContainer
>();
606 for (AbstractGroup group
: getAllGroups()) {
607 groupedComposites
.addAll(group
.getGroupedContainers());
610 return groupedComposites
;
618 * @return a {@link java.util.List} object.
620 public List
<AbstractGroup
> getAllGroups() {
621 List
<AbstractGroup
> allGroups
= new ArrayList
<AbstractGroup
>();
623 allGroups
.add(getAcceptedGroup());
625 // List<HomotypicalSynonymGroup> grps = getHeterotypicSynonymGroups(); // UNUSED => remove
627 heterotypicSynonymGroups
= getHeterotypicSynonymGroups();
629 if (heterotypicSynonymGroups
!= null) {
630 allGroups
.addAll(heterotypicSynonymGroups
);
633 if (misappliedGroup
!= null) {
634 allGroups
.add(misappliedGroup
);
643 * @see org.eclipse.ui.part.EditorPart#isDirty()
647 public boolean isDirty() {
648 return editor
.isDirty();
654 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
658 public void dispose() {
659 conversation
.unregisterForDataStoreChanges(this);
666 * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
670 public boolean isSaveAsAllowed() {
677 * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.
678 * IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
682 public void selectionChanged(IWorkbenchPart part
, ISelection selection
) {
691 * @return a {@link eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor}
695 public TaxonNameEditor
getEditor() {
701 * Getter for the field <code>selectedObject</code>.
705 * {@link eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer}
708 public AbstractGroupedContainer
getSelectedContainer() {
710 TaxonBase selectedTaxonBase
= null;
712 TaxonEditorInput input
= (TaxonEditorInput
) editor
.getEditorInput();
713 if (input
.getInitiallySelectedTaxonBase() != null) {
714 selectedTaxonBase
= input
.getInitiallySelectedTaxonBase();
716 if (selection
!= null) {
717 selectedTaxonBase
= selection
;
721 return (selectedTaxonBase
!= null) ?
getContainer(selectedTaxonBase
)
722 : getAcceptedNameContainer();
731 public void dragEntered() {
733 getControl().setBackground(
734 AbstractUtility
.getColor(Resources
.COLOR_DRAG_ENTER
));
743 public void dragLeft() {
744 getControl().setBackground(
745 AbstractUtility
.getColor(Resources
.COLOR_COMPOSITE_BACKGROUND
));
751 * setMisapplicationsGroup
754 * @param misappliedGroup
756 * {@link eu.etaxonomy.taxeditor.editor.name.container.MisappliedGroup}
759 public void setMisapplicationsGroup(MisappliedGroup misappliedGroup
) {
760 this.misappliedGroup
= misappliedGroup
;
767 * eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage#isRedrawing()
777 public boolean isRedrawing() {
786 * @return a {@link org.eclipse.ui.forms.widgets.FormToolkit} object.
788 public FormToolkit
getToolkit() {
789 return managedForm
.getToolkit();
794 * getHeterotypicSynonymGroups
797 * @return a {@link java.util.List} object.
799 public List
<HomotypicalSynonymGroup
> getHeterotypicSynonymGroups() {
800 return heterotypicSynonymGroups
;
805 * addHeterotypicSynonymGroup
810 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
813 public void addHeterotypicSynonymGroup(HomotypicalSynonymGroup group
) {
814 heterotypicSynonymGroups
.add(group
);
819 * getHomotypicSynonymGroup
823 * {@link eu.etaxonomy.taxeditor.editor.name.container.HomotypicalSynonymGroup}
826 public AcceptedGroup
getAcceptedGroup() {
827 return acceptedGroup
;
832 * @param acceptedGroup
834 public void setAcceptedGroup(AcceptedGroup acceptedGroup
) {
835 this.acceptedGroup
= acceptedGroup
;
840 * Getter for the field <code>misappliedGroup</code>.
844 * {@link eu.etaxonomy.taxeditor.editor.name.container.MisappliedGroup}
847 public MisappliedGroup
getMisappliedGroup() {
848 return misappliedGroup
;
851 // TODO not very useful at the moment
859 public boolean isActive() {
860 return editor
.equals(AbstractUtility
.getActiveE4Part());
871 public boolean onComplete() {
872 getContainer(objectAffectedByLastOperation
).setSelected();
878 public void partChanged(Integer eventType
, IWorkbenchPartReference partRef
) {
879 if (!partRef
.getPart(false).equals(editor
)) {
880 // getSelectedObject().colorSelected(AbstractGroupedContainer.SELECTED_NO_FOCUS);
885 * @param retainedGroup
887 public void removeGroup(AbstractGroup group
) {
891 //if (heterotypicSynonymGroups != null) {
892 heterotypicSynonymGroups
.remove(group
);
901 public AbstractGroupedContainer
getContainer(TaxonBase taxonBase
) {
902 List
<AbstractGroupedContainer
> groupedContainers
= getGroupedContainers();
903 for (AbstractGroupedContainer container
: groupedContainers
) {
904 if (container
.getData().equals(taxonBase
)
905 && container
.getNameViewer().getTextWidget() != null) {
909 return getAcceptedNameContainer();
913 * @see eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage#setOnError()
916 public void setOnError() {
917 Color disabledColor
= AbstractUtility
.getColor(Resources
.COLOR_EDITOR_ERROR
);
918 setEnabled(false, disabledColor
);
922 * @see eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage#setDisabled()
925 public void setDisabled(){
926 Color disabledColor
= AbstractUtility
.getColor(Resources
.COLOR_TEXT_DISABLED_BACKGROUND
);
930 protected void setEnabled(boolean enabled
, Color background
) {
932 for(AbstractGroupedContainer groupedContainer
: getGroupedContainers()){
933 groupedContainer
.setEnabled(enabled
);
936 // send an empty selection to the current provider - TODO only on error ???
938 getManagedForm().setInput(null);
940 for (AbstractGroupedContainer groupedContainer
: getGroupedContainers()) {
941 groupedContainer
.setBackground(background
);
944 getControl().setBackground(background
);
948 public void setEnabled(boolean enabled
) {
949 Color background
= AbstractUtility
.getColor(enabled ? Resources
.COLOR_COMPOSITE_BACKGROUND
: Resources
.COLOR_TEXT_DISABLED_BACKGROUND
);
950 setEnabled(enabled
, background
);