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 public TaxonNameEditor(MultiPageTaxonEditor editor
){
71 * Shared listener that sets dirty state to true
72 * when any registered property changes
74 private PropertyChangeListener taxonChangeListener
= new PropertyChangeListener() {
75 public void propertyChange(PropertyChangeEvent event
) {
76 if (event
.getPropertyName().equals(Resources
.PROPERTY_SHEET_CHANGE
)) {
77 firePropertyChange(PROP_DIRTY
);
82 private Map
<HomotypicalGroup
, HomotypicalGroupComposite
> homotypicGroupComposites
;
84 private MisappliedGroupComposite misappliedGroupComposite
;
86 private ConceptGroupComposite conceptGroupComposite
;
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 return misappliedGroupComposite
;
273 public Composite
getMisappliedName(Taxon misappliedName
) {
274 for(Control child
: getMisappliedGroup().getChildren()){
275 if(child
instanceof MisappliedNameComposite
){
276 return (MisappliedNameComposite
) child
;
283 public Composite
getSynonym(Synonym synonym
) {
285 GroupComposite groupComposite
= getHomotypicGroup(synonym
.getHomotypicGroup());
287 for (Control child
: groupComposite
.getChildren()){
288 if(child
instanceof SynonymComposite
289 && synonym
.equals(((SynonymComposite
) child
).getSynonym())){
290 return (SynonymComposite
) child
;
298 public Composite
getConceptGroup() {
299 return conceptGroupComposite
;
303 public Composite
getConcept(Taxon relatedConcept
) {
304 for (Control child
: getConceptGroup().getChildren()){
305 if(child
instanceof ConceptComposite
306 && relatedConcept
.equals
307 (((ConceptComposite
) child
).getRelatedTaxon())){
308 return (ConceptComposite
) child
;
316 * @see eu.etaxonomy.taxeditor.editor.AbstractTaxonEditor#getID()
319 public String
getID() {
320 return TaxonNameEditor
.ID
;
324 * @return a Set containing all composites that have been edited
326 public Set
<NameComposite
<TaxonBase
>> getDirtyNames(){
327 Set
<NameComposite
<TaxonBase
>> dirtyNames
= new HashSet
<NameComposite
<TaxonBase
>>();
329 for(GroupedComposite composite
: getGroupedComposites()){
330 if(composite
instanceof NameComposite
&& ((NameComposite
)composite
).isDirty()){
331 dirtyNames
.add((NameComposite
) composite
);
338 /***********************************************************************/
340 private GroupedComposite
createAcceptedTaxon() {
341 // Create a homotypic group composite for the accepted taxon
342 HomotypicalGroup group
= getTaxon().getHomotypicGroup();
343 Assert
.isNotNull(group
, "Taxon does not have a homotypic group");
345 createHomotypicalGroup(group
);
347 // Create a name composite for the accepted taxon
348 return new AcceptedNameComposite(this, getHomotypicGroup(group
));
351 private HomotypicalGroupComposite
createHomotypicalGroup(HomotypicalGroup group
) {
353 // Create the group composite
354 HomotypicalGroupComposite groupComposite
= new HomotypicalGroupComposite(this, getTopLevelComposite(), group
);
357 //groupComposite.addFocusListener(new CompositeBorderDecorator(groupComposite, editor.getManagedForm()));
359 groupComposite
.setData(FormToolkit
.KEY_DRAW_BORDER
, FormToolkit
.TEXT_BORDER
);
360 getManagedForm().getToolkit().paintBordersFor(groupComposite
.getParent());
362 getHomotypicGroups().put(group
, groupComposite
);
364 return groupComposite
;
368 private Composite
createSynonym(Synonym synonym
) {
369 // Get the synonym's homotypic group
370 HomotypicalGroup group
= synonym
.getHomotypicGroup();
371 Assert
.isNotNull(group
, "Synonym does not have a homotypic group");
373 // If the group doesn't yet have a composite, create one and add it to the repository
374 HomotypicalGroupComposite groupComposite
= getHomotypicGroup(group
);
375 if (groupComposite
== null) {
376 groupComposite
= createHomotypicalGroup(group
);
379 // Create a synonym composite in the homotypical group
380 Composite synonymComposite
= new SynonymComposite(this, groupComposite
, synonym
);
382 return synonymComposite
;
385 public Composite
createMisappliedName(Taxon misappliedName
) {
387 // If there is no composite for misapplied names,
388 // create one and add it to the repository
389 Composite groupComposite
= getMisappliedGroup();
390 if (groupComposite
== null) {
391 groupComposite
= createMisappliedGroup();
394 // Create the name's composite
395 Composite composite
= new MisappliedNameComposite(this, groupComposite
, misappliedName
);
401 public MisappliedGroupComposite
createMisappliedGroup() {
402 // Create the group composite
403 misappliedGroupComposite
= new MisappliedGroupComposite(this, this.getTopLevelComposite());
404 misappliedGroupComposite
.addFocusListener(new CompositeBorderDecorator(misappliedGroupComposite
, this.getManagedForm()));
406 // Put the group composite before concept group composite, if any
407 Composite conceptGroupComposite
= this.getConceptGroup();
408 if (conceptGroupComposite
!= null) {
409 misappliedGroupComposite
.moveAbove(conceptGroupComposite
);
412 return misappliedGroupComposite
;
416 public Composite
createConcept(TaxonRelationship relationship
) {
417 // If there is no composite for misapplied names,
418 // create one and add it to the repository
419 Composite groupComposite
= this.getConceptGroup();
420 if (groupComposite
== null) {
421 groupComposite
= createConceptGroup();
424 // Create the name's composite
425 Composite composite
= ConceptComposite
.getNewInstance(this, groupComposite
, relationship
);
431 public Composite
createConceptGroup() {
432 // Create the group composite
433 conceptGroupComposite
= new ConceptGroupComposite(this, this.getTopLevelComposite());
434 conceptGroupComposite
.addFocusListener(new CompositeBorderDecorator(conceptGroupComposite
, this.getManagedForm()));
436 // Put the group composite after misapplied group composite, if any
437 Composite misappliedGroupComposite
= this.getMisappliedGroup();
438 if (misappliedGroupComposite
!= null) {
439 conceptGroupComposite
.moveBelow(misappliedGroupComposite
);
442 return conceptGroupComposite
;