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
.beans
.PropertyChangeEvent
;
13 import java
.beans
.PropertyChangeListener
;
14 import java
.util
.HashMap
;
15 import java
.util
.List
;
19 import org
.apache
.log4j
.Logger
;
20 import org
.eclipse
.core
.commands
.operations
.IUndoableOperation
;
21 import org
.eclipse
.core
.runtime
.Assert
;
22 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
23 import org
.eclipse
.swt
.dnd
.DND
;
24 import org
.eclipse
.swt
.dnd
.DropTarget
;
25 import org
.eclipse
.swt
.dnd
.DropTargetAdapter
;
26 import org
.eclipse
.swt
.dnd
.DropTargetEvent
;
27 import org
.eclipse
.swt
.dnd
.Transfer
;
28 import org
.eclipse
.swt
.widgets
.Composite
;
29 import org
.eclipse
.swt
.widgets
.Control
;
30 import org
.eclipse
.swt
.widgets
.Event
;
31 import org
.eclipse
.swt
.widgets
.Listener
;
32 import org
.eclipse
.ui
.IEditorInput
;
33 import org
.eclipse
.ui
.IEditorSite
;
34 import org
.eclipse
.ui
.PartInitException
;
35 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
37 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
38 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
39 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
40 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
41 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
42 import eu
.etaxonomy
.taxeditor
.editor
.AbstractTaxonEditor
;
43 import eu
.etaxonomy
.taxeditor
.editor
.CompositeBorderDecorator
;
44 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
45 import eu
.etaxonomy
.taxeditor
.editor
.GroupComposite
;
46 import eu
.etaxonomy
.taxeditor
.editor
.GroupedComposite
;
47 import eu
.etaxonomy
.taxeditor
.editor
.MultiPageTaxonEditor
;
48 import eu
.etaxonomy
.taxeditor
.editor
.WidgetTransfer
;
49 import eu
.etaxonomy
.taxeditor
.model
.Resources
;
50 import eu
.etaxonomy
.taxeditor
.operations
.ChangeConceptToSynonymOperation
;
51 import eu
.etaxonomy
.taxeditor
.operations
.ChangeHomotypicGroupOperation
;
58 public class TaxonNameEditor
extends AbstractTaxonEditor
59 implements INameEditorCompositeRepository
{
60 private static final Logger logger
= Logger
.getLogger(TaxonNameEditor
.class);
62 private static final String ID
= "eu.etaxonomy.taxeditor.taxonNameEditor";
65 public TaxonNameEditor(MultiPageTaxonEditor editor
){
70 * Shared listener that sets dirty state to true
71 * when any registered property changes
73 private PropertyChangeListener taxonChangeListener
= new PropertyChangeListener() {
74 public void propertyChange(PropertyChangeEvent event
) {
75 if (event
.getPropertyName().equals(Resources
.PROPERTY_SHEET_CHANGE
)) {
76 firePropertyChange(PROP_DIRTY
);
81 private Map
<HomotypicalGroup
, HomotypicalGroupComposite
> homotypicGroupComposites
;
83 private MisappliedGroupComposite misappliedGroupComposite
;
85 private ConceptGroupComposite conceptGroupComposite
;
88 public void doSave(IProgressMonitor monitor
) {}
91 public void doSaveAs() {}
94 public void init(IEditorSite site
, IEditorInput input
)
95 throws PartInitException
{
97 super.init(site
, input
);
99 // Register listeners for any change in accepted name or set of relations
100 taxon
.getName().addPropertyChangeListener(taxonChangeListener
);
101 taxon
.addPropertyChangeListener(taxonChangeListener
);
105 public boolean isDirty() {
110 public boolean isSaveAsAllowed() {
115 protected void createManagedForm(Composite composite
) {
117 super.createManagedForm(composite
);
119 Taxon taxon
= getTaxon();
121 firstGroupedComposite
= createAcceptedTaxon();
123 // Draw homotypic group synonyms
124 HomotypicalGroup homotypicGroup
= taxon
.getHomotypicGroup();
126 if (homotypicGroup
!= null) {
127 List
<Synonym
> homotypicSynonyms
= homotypicGroup
.getSynonymsInGroup(taxon
.getSec());
128 for (Synonym synonym
: homotypicSynonyms
) {
130 // Make sure synonym belongs to the taxon
131 if (synonym
.getAcceptedTaxa().contains(taxon
)) {
132 createSynonym(synonym
);
137 // Draw heterotypic synonym groups
138 List
<HomotypicalGroup
> heterotypicGroups
= taxon
.getHeterotypicSynonymyGroups();
139 for (HomotypicalGroup heterotypicGroup
: heterotypicGroups
) {
141 // Make sure this is not the taxon's homotypic group
142 if (!heterotypicGroup
.equals(homotypicGroup
)) {
144 List
<Synonym
> heterotypicSynonyms
= heterotypicGroup
.
145 getSynonymsInGroup(taxon
.getSec());
146 for (Synonym synonym
: heterotypicSynonyms
) {
148 // Make sure synonym belongs to the taxon
149 if (synonym
.getAcceptedTaxa().contains(taxon
)) {
150 createSynonym(synonym
);
156 // Draw misapplied name elements
157 for(Taxon misappliedName
: taxon
.getMisappliedNames()){
158 createMisappliedName(misappliedName
);
161 // Draw concept relation elements
162 Set
<TaxonRelationship
> taxonRelations
= taxon
.getTaxonRelations();
163 for (TaxonRelationship relationship
: taxonRelations
) {
165 if (relationship
.getType().equals(TaxonRelationshipType
.MISAPPLIED_NAME_FOR()) ||
166 relationship
.getType().equals(TaxonRelationshipType
.TAXONOMICALLY_INCLUDED_IN())) {
170 createConcept(relationship
);
185 private void createDragSupport() {
186 // Listen for names being dragged outside of existing homotypic groups -
187 // user wants to create a new group
188 Transfer
[] types
= new Transfer
[] {WidgetTransfer
.getInstance()};
189 int operations
= DND
.DROP_MOVE
| DND
.DROP_COPY
| DND
.DROP_DEFAULT
;
190 DropTarget target
= new DropTarget(parent
, operations
);
191 target
.setTransfer(types
);
192 target
.addDropListener(new DropTargetAdapter() {
194 public void drop(DropTargetEvent event
) {
196 if (event
.data
instanceof GroupedComposite
) {
197 final GroupedComposite composite
= (GroupedComposite
) event
.data
;
198 if (composite
.getDragSource() != null) {
200 // Execute operations at end of drag event
201 composite
.getDragSource().addListener(DND
.DragEnd
, new Listener() {
203 public void handleEvent(Event event
) {
204 IUndoableOperation operation
= null;
206 // Synonym being dropped
207 if(composite
instanceof SynonymComposite
){
208 Synonym synonym
= ((SynonymComposite
)composite
).getSynonym();
209 operation
= new ChangeHomotypicGroupOperation
210 ("change type", getUndoContext(),
211 getTaxon(), synonym
, HomotypicalGroup
.NewInstance(), TaxonNameEditor
.this);
214 // Misapplied name being dropped
215 if(composite
instanceof MisappliedNameComposite
){
216 Taxon misapplication
= ((MisappliedNameComposite
)composite
).getMisappliedName();
217 operation
= new ChangeConceptToSynonymOperation
218 ("change misapplied name to synonym", getUndoContext(),
219 getTaxon(), misapplication
, HomotypicalGroup
.NewInstance(), TaxonNameEditor
.this);
222 // Execute operation if it's been init'ed
223 if (operation
== null) {
224 logger
.warn("User unsuccessfully tried to drop " + composite
.getClass());
226 EditorUtil
.executeOperation(operation
);
238 public Composite
getAcceptedName() {
239 // accepted name should always reside in firstGroupComposite
240 if(firstGroupedComposite
instanceof AcceptedNameComposite
){
241 return firstGroupedComposite
;
244 // for(Composite c : getGroupedComposites()){
245 // if(c instanceof AcceptedNameComposite){
255 private Map
<HomotypicalGroup
, HomotypicalGroupComposite
> getHomotypicGroups() {
256 if(homotypicGroupComposites
== null){
257 homotypicGroupComposites
= new HashMap
<HomotypicalGroup
, HomotypicalGroupComposite
>();
259 return homotypicGroupComposites
;
262 public HomotypicalGroupComposite
getHomotypicGroup(HomotypicalGroup group
) {
263 return getHomotypicGroups().get(group
);
267 public Composite
getMisappliedGroup() {
268 return misappliedGroupComposite
;
272 public Composite
getMisappliedName(Taxon misappliedName
) {
273 for(Control child
: getMisappliedGroup().getChildren()){
274 if(child
instanceof MisappliedNameComposite
){
275 return (MisappliedNameComposite
) child
;
282 public Composite
getSynonym(Synonym synonym
) {
284 GroupComposite groupComposite
= getHomotypicGroup(synonym
.getHomotypicGroup());
286 for (Control child
: groupComposite
.getChildren()){
287 if(child
instanceof SynonymComposite
288 && synonym
.equals(((SynonymComposite
) child
).getSynonym())){
289 return (SynonymComposite
) child
;
297 public Composite
getConceptGroup() {
298 return conceptGroupComposite
;
302 public Composite
getConcept(Taxon relatedConcept
) {
303 for (Control child
: getConceptGroup().getChildren()){
304 if(child
instanceof ConceptComposite
305 && relatedConcept
.equals
306 (((ConceptComposite
) child
).getRelatedTaxon())){
307 return (ConceptComposite
) child
;
315 * @see eu.etaxonomy.taxeditor.editor.AbstractTaxonEditor#getID()
318 public String
getID() {
319 return TaxonNameEditor
.ID
;
323 /***********************************************************************/
325 private GroupedComposite
createAcceptedTaxon() {
326 // Create a homotypic group composite for the accepted taxon
327 HomotypicalGroup group
= getTaxon().getHomotypicGroup();
328 Assert
.isNotNull(group
, "Taxon does not have a homotypic group");
330 createHomotypicalGroup(group
);
332 // Create a name composite for the accepted taxon
333 return new AcceptedNameComposite(this, getHomotypicGroup(group
));
336 private HomotypicalGroupComposite
createHomotypicalGroup(HomotypicalGroup group
) {
338 // Create the group composite
339 HomotypicalGroupComposite groupComposite
= new HomotypicalGroupComposite(this, getTopLevelComposite(), group
);
342 //groupComposite.addFocusListener(new CompositeBorderDecorator(groupComposite, editor.getManagedForm()));
344 groupComposite
.setData(FormToolkit
.KEY_DRAW_BORDER
, FormToolkit
.TEXT_BORDER
);
345 getManagedForm().getToolkit().paintBordersFor(groupComposite
.getParent());
347 getHomotypicGroups().put(group
, groupComposite
);
349 return groupComposite
;
353 private Composite
createSynonym(Synonym synonym
) {
354 // Get the synonym's homotypic group
355 HomotypicalGroup group
= synonym
.getHomotypicGroup();
356 Assert
.isNotNull(group
, "Synonym does not have a homotypic group");
358 // If the group doesn't yet have a composite, create one and add it to the repository
359 HomotypicalGroupComposite groupComposite
= getHomotypicGroup(group
);
360 if (groupComposite
== null) {
361 groupComposite
= createHomotypicalGroup(group
);
364 // Create a synonym composite in the homotypical group
365 Composite synonymComposite
= new SynonymComposite(this, groupComposite
, synonym
);
367 return synonymComposite
;
370 public Composite
createMisappliedName(Taxon misappliedName
) {
372 // If there is no composite for misapplied names,
373 // create one and add it to the repository
374 Composite groupComposite
= getMisappliedGroup();
375 if (groupComposite
== null) {
376 groupComposite
= createMisappliedGroup();
379 // Create the name's composite
380 Composite composite
= new MisappliedNameComposite(this, groupComposite
, misappliedName
);
386 public MisappliedGroupComposite
createMisappliedGroup() {
387 // Create the group composite
388 misappliedGroupComposite
= new MisappliedGroupComposite(this, this.getTopLevelComposite());
389 misappliedGroupComposite
.addFocusListener(new CompositeBorderDecorator(misappliedGroupComposite
, this.getManagedForm()));
391 // Put the group composite before concept group composite, if any
392 Composite conceptGroupComposite
= this.getConceptGroup();
393 if (conceptGroupComposite
!= null) {
394 misappliedGroupComposite
.moveAbove(conceptGroupComposite
);
397 return misappliedGroupComposite
;
401 public Composite
createConcept(TaxonRelationship relationship
) {
402 // If there is no composite for misapplied names,
403 // create one and add it to the repository
404 Composite groupComposite
= this.getConceptGroup();
405 if (groupComposite
== null) {
406 groupComposite
= createConceptGroup();
409 // Create the name's composite
410 Composite composite
= ConceptComposite
.getNewInstance(this, groupComposite
, relationship
);
416 public Composite
createConceptGroup() {
417 // Create the group composite
418 conceptGroupComposite
= new ConceptGroupComposite(this, this.getTopLevelComposite());
419 conceptGroupComposite
.addFocusListener(new CompositeBorderDecorator(conceptGroupComposite
, this.getManagedForm()));
421 // Put the group composite after misapplied group composite, if any
422 Composite misappliedGroupComposite
= this.getMisappliedGroup();
423 if (misappliedGroupComposite
!= null) {
424 conceptGroupComposite
.moveBelow(misappliedGroupComposite
);
427 return conceptGroupComposite
;