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
.HashSet
;
16 import java
.util
.List
;
20 import org
.apache
.log4j
.Logger
;
21 import org
.eclipse
.core
.commands
.operations
.IUndoableOperation
;
22 import org
.eclipse
.core
.runtime
.Assert
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.swt
.dnd
.DND
;
25 import org
.eclipse
.swt
.dnd
.DropTarget
;
26 import org
.eclipse
.swt
.dnd
.DropTargetAdapter
;
27 import org
.eclipse
.swt
.dnd
.DropTargetEvent
;
28 import org
.eclipse
.swt
.dnd
.Transfer
;
29 import org
.eclipse
.swt
.widgets
.Composite
;
30 import org
.eclipse
.swt
.widgets
.Control
;
31 import org
.eclipse
.swt
.widgets
.Event
;
32 import org
.eclipse
.swt
.widgets
.Listener
;
33 import org
.eclipse
.ui
.IEditorInput
;
34 import org
.eclipse
.ui
.IEditorSite
;
35 import org
.eclipse
.ui
.PartInitException
;
36 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
38 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
39 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
40 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
41 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
42 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
43 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
44 import eu
.etaxonomy
.taxeditor
.editor
.AbstractTaxonEditor
;
45 import eu
.etaxonomy
.taxeditor
.editor
.CompositeBorderDecorator
;
46 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
47 import eu
.etaxonomy
.taxeditor
.editor
.GroupComposite
;
48 import eu
.etaxonomy
.taxeditor
.editor
.GroupedComposite
;
49 import eu
.etaxonomy
.taxeditor
.editor
.MultiPageTaxonEditor
;
50 import eu
.etaxonomy
.taxeditor
.editor
.WidgetTransfer
;
51 import eu
.etaxonomy
.taxeditor
.model
.Resources
;
52 import eu
.etaxonomy
.taxeditor
.operations
.ChangeConceptToSynonymOperation
;
53 import eu
.etaxonomy
.taxeditor
.operations
.ChangeHomotypicGroupOperation
;
60 public class TaxonNameEditor
extends AbstractTaxonEditor
61 implements INameEditorCompositeRepository
{
62 private static final Logger logger
= Logger
.getLogger(TaxonNameEditor
.class);
64 private static final String ID
= "eu.etaxonomy.taxeditor.taxonNameEditor";
66 private Map
<HomotypicalGroup
, HomotypicalGroupComposite
> homotypicGroupComposites
;
68 private MisappliedGroupComposite misappliedGroupComposite
;
70 private ConceptGroupComposite conceptGroupComposite
;
72 public TaxonNameEditor(MultiPageTaxonEditor editor
){
77 * Shared listener that sets dirty state to true
78 * when any registered property changes
80 private PropertyChangeListener taxonChangeListener
= new PropertyChangeListener() {
81 public void propertyChange(PropertyChangeEvent event
) {
82 if (event
.getPropertyName().equals(Resources
.PROPERTY_SHEET_CHANGE
)) {
83 firePropertyChange(PROP_DIRTY
);
89 public void doSave(IProgressMonitor monitor
) {}
92 public void doSaveAs() {}
95 public void init(IEditorSite site
, IEditorInput input
)
96 throws PartInitException
{
98 super.init(site
, input
);
100 // Register listeners for any change in accepted name or set of relations
101 taxon
.getName().addPropertyChangeListener(taxonChangeListener
);
102 taxon
.addPropertyChangeListener(taxonChangeListener
);
106 public boolean isDirty() {
111 public boolean isSaveAsAllowed() {
116 protected void createManagedForm(Composite composite
) {
118 super.createManagedForm(composite
);
120 Taxon taxon
= getTaxon();
122 firstGroupedComposite
= createAcceptedTaxon();
124 // Draw homotypic group synonyms
125 HomotypicalGroup homotypicGroup
= taxon
.getHomotypicGroup();
127 if (homotypicGroup
!= null) {
128 List
<Synonym
> homotypicSynonyms
= homotypicGroup
.getSynonymsInGroup(taxon
.getSec());
129 for (Synonym synonym
: homotypicSynonyms
) {
131 // Make sure synonym belongs to the taxon
132 if (synonym
.getAcceptedTaxa().contains(taxon
)) {
133 createSynonym(synonym
);
138 // Draw heterotypic synonym groups
139 List
<HomotypicalGroup
> heterotypicGroups
= taxon
.getHeterotypicSynonymyGroups();
140 for (HomotypicalGroup heterotypicGroup
: heterotypicGroups
) {
142 // Make sure this is not the taxon's homotypic group
143 if (!heterotypicGroup
.equals(homotypicGroup
)) {
145 List
<Synonym
> heterotypicSynonyms
= heterotypicGroup
.
146 getSynonymsInGroup(taxon
.getSec());
147 for (Synonym synonym
: heterotypicSynonyms
) {
149 // Make sure synonym belongs to the taxon
150 if (synonym
.getAcceptedTaxa().contains(taxon
)) {
151 createSynonym(synonym
);
157 // Draw misapplied name elements
158 for(Taxon misappliedName
: taxon
.getMisappliedNames()){
159 createMisappliedName(misappliedName
);
162 // Draw concept relation elements
163 Set
<TaxonRelationship
> taxonRelations
= taxon
.getTaxonRelations();
164 for (TaxonRelationship relationship
: taxonRelations
) {
166 if (relationship
.getType().equals(TaxonRelationshipType
.MISAPPLIED_NAME_FOR()) ||
167 relationship
.getType().equals(TaxonRelationshipType
.TAXONOMICALLY_INCLUDED_IN())) {
171 createConcept(relationship
);
186 private void createDragSupport() {
187 // Listen for names being dragged outside of existing homotypic groups -
188 // user wants to create a new group
189 Transfer
[] types
= new Transfer
[] {WidgetTransfer
.getInstance()};
190 int operations
= DND
.DROP_MOVE
| DND
.DROP_COPY
| DND
.DROP_DEFAULT
;
191 DropTarget target
= new DropTarget(parent
, operations
);
192 target
.setTransfer(types
);
193 target
.addDropListener(new DropTargetAdapter() {
195 public void drop(DropTargetEvent event
) {
197 if (event
.data
instanceof GroupedComposite
) {
198 final GroupedComposite composite
= (GroupedComposite
) event
.data
;
199 if (composite
.getDragSource() != null) {
201 // Execute operations at end of drag event
202 composite
.getDragSource().addListener(DND
.DragEnd
, new Listener() {
204 public void handleEvent(Event event
) {
205 IUndoableOperation operation
= null;
207 // Synonym being dropped
208 if(composite
instanceof SynonymComposite
){
209 Synonym synonym
= ((SynonymComposite
)composite
).getSynonym();
210 operation
= new ChangeHomotypicGroupOperation
211 ("change type", getUndoContext(),
212 getTaxon(), synonym
, HomotypicalGroup
.NewInstance(), TaxonNameEditor
.this);
215 // Misapplied name being dropped
216 if(composite
instanceof MisappliedNameComposite
){
217 Taxon misapplication
= ((MisappliedNameComposite
)composite
).getMisappliedName();
218 operation
= new ChangeConceptToSynonymOperation
219 ("change misapplied name to synonym", getUndoContext(),
220 getTaxon(), misapplication
, HomotypicalGroup
.NewInstance(), TaxonNameEditor
.this);
223 // Execute operation if it's been init'ed
224 if (operation
== null) {
225 logger
.warn("User unsuccessfully tried to drop " + composite
.getClass());
227 EditorUtil
.executeOperation(operation
);
239 public Composite
getAcceptedName() {
240 // accepted name should always reside in firstGroupComposite
241 if(firstGroupedComposite
instanceof AcceptedNameComposite
){
242 return firstGroupedComposite
;
245 // for(Composite c : getGroupedComposites()){
246 // if(c instanceof AcceptedNameComposite){
256 private Map
<HomotypicalGroup
, HomotypicalGroupComposite
> getHomotypicGroups() {
257 if(homotypicGroupComposites
== null){
258 homotypicGroupComposites
= new HashMap
<HomotypicalGroup
, HomotypicalGroupComposite
>();
260 return homotypicGroupComposites
;
263 public HomotypicalGroupComposite
getHomotypicGroup(HomotypicalGroup group
) {
264 return getHomotypicGroups().get(group
);
268 public Composite
getMisappliedGroup() {
269 if (misappliedGroupComposite
== null) {
270 misappliedGroupComposite
= createMisappliedGroup();
272 return misappliedGroupComposite
;
276 public Composite
getMisappliedName(Taxon misappliedName
) {
277 for(Control child
: getMisappliedGroup().getChildren()){
278 if(child
instanceof MisappliedNameComposite
){
279 return (MisappliedNameComposite
) child
;
286 public Composite
getSynonym(Synonym synonym
) {
288 GroupComposite groupComposite
= getHomotypicGroup(synonym
.getHomotypicGroup());
290 for (Control child
: groupComposite
.getChildren()){
291 if(child
instanceof SynonymComposite
292 && synonym
.equals(((SynonymComposite
) child
).getSynonym())){
293 return (SynonymComposite
) child
;
301 public Composite
getConceptGroup() {
302 if (conceptGroupComposite
== null) {
303 conceptGroupComposite
= createConceptGroup();
305 return conceptGroupComposite
;
309 public Composite
getConcept(Taxon relatedConcept
) {
310 for (Control child
: getConceptGroup().getChildren()){
311 if(child
instanceof ConceptComposite
312 && relatedConcept
.equals
313 (((ConceptComposite
) child
).getRelatedTaxon())){
314 return (ConceptComposite
) child
;
322 * @see eu.etaxonomy.taxeditor.editor.AbstractTaxonEditor#getID()
325 public String
getID() {
326 return TaxonNameEditor
.ID
;
330 * @return a Set containing all composites that have been edited
332 public Set
<NameComposite
<TaxonBase
>> getDirtyNames(){
333 Set
<NameComposite
<TaxonBase
>> dirtyNames
= new HashSet
<NameComposite
<TaxonBase
>>();
335 for(GroupedComposite composite
: getGroupedComposites()){
336 if(composite
instanceof NameComposite
&& ((NameComposite
)composite
).isDirty()){
337 dirtyNames
.add((NameComposite
) composite
);
344 /***********************************************************************/
346 private GroupedComposite
createAcceptedTaxon() {
347 // Create a homotypic group composite for the accepted taxon
348 HomotypicalGroup group
= getTaxon().getHomotypicGroup();
349 Assert
.isNotNull(group
, "Taxon does not have a homotypic group");
351 createHomotypicalGroup(group
);
353 // Create a name composite for the accepted taxon
354 return new AcceptedNameComposite(this, getHomotypicGroup(group
));
357 private HomotypicalGroupComposite
createHomotypicalGroup(HomotypicalGroup group
) {
359 // Create the group composite
360 HomotypicalGroupComposite groupComposite
= new HomotypicalGroupComposite(this, getTopLevelComposite(), group
);
363 //groupComposite.addFocusListener(new CompositeBorderDecorator(groupComposite, editor.getManagedForm()));
365 groupComposite
.setData(FormToolkit
.KEY_DRAW_BORDER
, FormToolkit
.TEXT_BORDER
);
366 getManagedForm().getToolkit().paintBordersFor(groupComposite
.getParent());
368 Map
<HomotypicalGroup
, HomotypicalGroupComposite
> groups
= getHomotypicGroups();
370 groups
.put(group
, groupComposite
);
372 return groupComposite
;
376 private Composite
createSynonym(Synonym synonym
) {
377 // Get the synonym's homotypic group
378 HomotypicalGroup group
= synonym
.getHomotypicGroup();
379 Assert
.isNotNull(group
, "Synonym does not have a homotypic group");
381 // If the group doesn't yet have a composite, create one and add it to the repository
382 HomotypicalGroupComposite groupComposite
= getHomotypicGroup(group
);
383 if (groupComposite
== null) {
384 groupComposite
= createHomotypicalGroup(group
);
387 // Create a synonym composite in the homotypical group
388 Composite synonymComposite
= new SynonymComposite(this, groupComposite
, synonym
);
390 return synonymComposite
;
393 public Composite
createMisappliedName(Taxon misappliedName
) {
395 // If there is no composite for misapplied names,
396 // create one and add it to the repository
397 Composite groupComposite
= getMisappliedGroup();
399 // Create the name's composite
400 Composite composite
= new MisappliedNameComposite(this, groupComposite
, misappliedName
);
406 public MisappliedGroupComposite
createMisappliedGroup() {
407 // Create the group composite
408 misappliedGroupComposite
= new MisappliedGroupComposite(this, this.getTopLevelComposite());
409 misappliedGroupComposite
.addFocusListener(new CompositeBorderDecorator(misappliedGroupComposite
, this.getManagedForm()));
411 // Put the group composite before concept group composite, if any
412 if (conceptGroupComposite
!= null) {
413 misappliedGroupComposite
.moveAbove(conceptGroupComposite
);
416 return misappliedGroupComposite
;
420 public Composite
createConcept(TaxonRelationship relationship
) {
421 // If there is no composite for misapplied names,
422 // create one and add it to the repository
423 Composite groupComposite
= this.getConceptGroup();
425 // Create the name's composite
426 Composite composite
= ConceptComposite
.getNewInstance(this, groupComposite
, relationship
);
432 public ConceptGroupComposite
createConceptGroup() {
433 // Create the group composite
434 conceptGroupComposite
= new ConceptGroupComposite(this, this.getTopLevelComposite());
435 conceptGroupComposite
.addFocusListener(new CompositeBorderDecorator(conceptGroupComposite
, this.getManagedForm()));
437 // Put the group composite after misapplied group composite, if any
438 if (misappliedGroupComposite
!= null) {
439 conceptGroupComposite
.moveBelow(misappliedGroupComposite
);
442 return conceptGroupComposite
;
447 * @see eu.etaxonomy.taxeditor.editor.AbstractTaxonEditor#resetGroupComposites()
450 protected void resetGroupComposites() {
451 conceptGroupComposite
= null;
452 misappliedGroupComposite
= null;
453 homotypicGroupComposites
= null;