Moved around a few classes between eu.etaxonomy.taxeditor.editor and eu.etaxonomy...
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / editor / name / NameComposite.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9
10 package eu.etaxonomy.taxeditor.editor.name;
11
12 import org.apache.log4j.Logger;
13 import org.eclipse.jface.action.Action;
14 import org.eclipse.jface.util.IPropertyChangeListener;
15 import org.eclipse.swt.events.FocusAdapter;
16 import org.eclipse.swt.events.FocusEvent;
17 import org.eclipse.swt.graphics.Font;
18 import org.eclipse.swt.graphics.Image;
19 import org.eclipse.swt.widgets.Composite;
20 import org.eclipse.ui.forms.IManagedForm;
21
22 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
23 import eu.etaxonomy.cdm.model.name.NonViralName;
24 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
25 import eu.etaxonomy.cdm.model.taxon.Synonym;
26 import eu.etaxonomy.cdm.model.taxon.Taxon;
27 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
28 import eu.etaxonomy.taxeditor.ITaxEditorConstants;
29 import eu.etaxonomy.taxeditor.TaxEditorPlugin;
30 import eu.etaxonomy.taxeditor.actions.ui.AdaptCompositeToGroupAction;
31 import eu.etaxonomy.taxeditor.actions.ui.AddBasionymCompositeAction;
32 import eu.etaxonomy.taxeditor.actions.ui.ChangeCompositeToMisappliedNameAction;
33 import eu.etaxonomy.taxeditor.actions.ui.ChangeCompositeToNewTaxonAction;
34 import eu.etaxonomy.taxeditor.actions.ui.ChangeSynonymToTaxonUiAction;
35 import eu.etaxonomy.taxeditor.actions.ui.ChangeTaxonToSynonymAction;
36 import eu.etaxonomy.taxeditor.actions.ui.CreateNewHeterotypicCompositeAction;
37 import eu.etaxonomy.taxeditor.actions.ui.DeleteMisappliedNameCompositeAction;
38 import eu.etaxonomy.taxeditor.actions.ui.DeleteSynonymCompositeAction;
39 import eu.etaxonomy.taxeditor.actions.ui.MoveCompositeToMisappliedCompositeAction;
40 import eu.etaxonomy.taxeditor.actions.ui.MoveTaxonDialogAction;
41 import eu.etaxonomy.taxeditor.actions.ui.RemoveBasionymCompositeAction;
42 import eu.etaxonomy.taxeditor.editor.ContextMenu;
43 import eu.etaxonomy.taxeditor.editor.EditorGroupComposite;
44 import eu.etaxonomy.taxeditor.editor.EditorGroupedComposite;
45 import eu.etaxonomy.taxeditor.editor.EmptyTextViewerPrompt;
46 import eu.etaxonomy.taxeditor.editor.LineBreakListener;
47 import eu.etaxonomy.taxeditor.editor.ParseListener;
48 import eu.etaxonomy.taxeditor.model.CdmUtil;
49
50 /**
51 * Formats an <code>EditorGroupedComposite</code> to display <code>TaxonNameBase</code> elements
52 * in a <code>NameViewer</code>.
53 *
54 * <code>Composite.getData()</code> returns <code>TaxonBase</code>. Therefore, the method
55 * <code>setSelection()</code> is overriden to send the property sheet <code>TaxonBase.getName()</code>.
56 *
57 * @author p.ciardelli
58 * @created 02.06.2008
59 * @version 1.0
60 */
61 public class NameComposite extends EditorGroupedComposite {
62 private static final Logger logger = Logger.getLogger(NameComposite.class);
63
64 /**
65 * ************ COMPOSITE TYPES ************
66 */
67 public String compositeType;
68 public static final String ACCEPTED_TAXON = "accepted_name_composite";
69 public static final String HOMOTYPIC_SYNONYM = "homotypic_name_composite";
70 public static final String HETEROTYPIC_SYNONYM = "heterotypic_name_composite";
71 public static final String MISAPPLIED_NAME = "misappliedname_name_composite";
72
73 /**
74 * ************ INDENTATIONS ************
75 */
76 public static final int ACCEPTED_INDENT = 0;
77 public static final int SYNONYM_INDENT = 15;
78 public static final int MISAPPLIEDNAME_INDENT = 15;
79
80 /**
81 * ************ FONTS ************
82 */
83 public static final Font ACCEPTED_FONT = TaxEditorPlugin.getDefault()
84 .getFont(ITaxEditorConstants.ACCEPTED_TAXON_FONT);
85 public static final Font SYNONYM_FONT = TaxEditorPlugin.getDefault()
86 .getFont(ITaxEditorConstants.SYNONYM_FONT);
87 public static final Font MISAPPLIEDNAME_FONT = TaxEditorPlugin.getDefault()
88 .getFont(ITaxEditorConstants.MISAPPLIEDNAME_FONT);
89
90 /**
91 * ************ ICONS ************
92 */
93 public static final Image ACCEPTED_ICON = TaxEditorPlugin.getDefault()
94 .getImage(ITaxEditorConstants.BLACK_SQUARE_ICON);
95 public static final Image HOMOTYPIC_SYNONYM_ICON = TaxEditorPlugin
96 .getDefault().getImage(ITaxEditorConstants.HOMOTYPIC_SYN_ICON);
97 public static final Image HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON = TaxEditorPlugin
98 .getDefault().getImage(
99 ITaxEditorConstants.HOMOTYPIC_SYN_ORIGINAL_ICON);
100 public static final Image HETEROTYPIC_SYNONYM_ICON = TaxEditorPlugin
101 .getDefault().getImage(ITaxEditorConstants.HETEROTYPIC_SYN_ICON);
102 public static final Image HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON = TaxEditorPlugin
103 .getDefault().getImage(
104 ITaxEditorConstants.HETEROTYPIC_SYN_ORIGINAL_ICON);
105 public static final Image MISAPPLIEDNAME_ICON = TaxEditorPlugin
106 .getDefault().getImage(ITaxEditorConstants.MISAPPLIED_NAME_ICON);
107 public static final Image AUTONYM_ICON = TaxEditorPlugin.getDefault()
108 .getImage(ITaxEditorConstants.AUTONYM_ICON);
109 public static final Image BASIONYM_ICON = TaxEditorPlugin.getDefault()
110 .getImage(ITaxEditorConstants.BASIONYM_ICON);
111 public static final Image MOVE = TaxEditorPlugin.getDefault().getImage(
112 ITaxEditorConstants.MOVE_ICON);
113
114 /**
115 * ************ TRANSFORMATIONS ************
116 */
117 public static final String ADD_GROUP_BASIONYM = "add_group_basionym";
118 public static final String REMOVE_GROUP_BASIONYM = "remove_group_basionym";
119
120 /**
121 * ************ MENU ACTIONS ************
122 */
123 public Action CHANGE_TAXON_TO_SYNONYM_ACTION;
124
125 private static final String EMPTY_NAME_PROMPT = "Click to add name";
126
127 /**
128 * The constructor for a DescriptionElementComposite. Takes a parent Composite on which to
129 * create itself, and an IManagedForm for Composite life cycle methods, i.e.
130 * drawing borders, creating other Composites, creating line wrap support,
131 * etc.
132 *
133 * @param parent
134 * @param managedForm
135 */
136 public NameComposite(Composite parent, IManagedForm managedForm, String compositeType, TaxonBase data) {
137 super(parent, managedForm);
138
139 createNameViewer();
140 createBorderSupport();
141 createLineWrapSupport();
142
143 setData(data);
144 transform(compositeType);
145
146 createEmptyViewerPrompt(EMPTY_NAME_PROMPT);
147 setFocus();
148 }
149
150 /**
151 * All cosmetic - non-data-related, i.e. icons, fonts, etc. -
152 * transformations take place in this method.
153 *
154 * @param transformation
155 */
156 public void transform(String transformation) {
157
158 if (transformation.equals(ADD_GROUP_BASIONYM)) {
159 if (compositeType.equals(HOMOTYPIC_SYNONYM)) {
160 setIcon(HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON);
161 } else {
162 setIcon(HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON);
163 }
164 }
165
166 if (transformation.equals(REMOVE_GROUP_BASIONYM)) {
167 if (compositeType.equals(HOMOTYPIC_SYNONYM)) {
168 setIcon(HOMOTYPIC_SYNONYM_ICON);
169 } else {
170 setIcon(HETEROTYPIC_SYNONYM_ICON);
171 }
172 }
173
174 if (transformation.equals(ACCEPTED_TAXON)) {
175 setDraggable(false);
176 setIcon(ACCEPTED_ICON);
177 setFont(ACCEPTED_FONT);
178 setIndent(ACCEPTED_INDENT);
179
180 createAcceptedMenu();
181
182 compositeType = ACCEPTED_TAXON;
183 }
184
185 if (transformation.equals(HOMOTYPIC_SYNONYM)
186 || transformation.equals(HETEROTYPIC_SYNONYM)) {
187 setDraggable(true);
188 setFont(SYNONYM_FONT);
189 setIndent(SYNONYM_INDENT);
190
191 createSynonymMenu();
192 }
193
194 if (transformation.equals(HOMOTYPIC_SYNONYM)) {
195 if (!(getData() instanceof Synonym)) {
196 return;
197 }
198 Synonym synonym = (Synonym) getData();
199 if (CdmUtil.isNameGroupBasionym(synonym.getName())) {
200 setIcon(HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON);
201 } else {
202 setIcon(HOMOTYPIC_SYNONYM_ICON);
203 }
204 compositeType = HOMOTYPIC_SYNONYM;
205 }
206
207 if (transformation.equals(HETEROTYPIC_SYNONYM)) {
208 if (!(getData() instanceof Synonym)) {
209 return;
210 }
211 Synonym synonym = (Synonym) getData();
212 if (CdmUtil.isNameGroupBasionym(synonym.getName())) {
213 setIcon(HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON);
214 } else {
215 setIcon(HETEROTYPIC_SYNONYM_ICON);
216 }
217 compositeType = HETEROTYPIC_SYNONYM;
218 }
219
220 if (transformation.equals(MISAPPLIED_NAME)) {
221
222 setDraggable(true);
223 setIcon(MISAPPLIEDNAME_ICON);
224 setFont(MISAPPLIEDNAME_FONT);
225 setIndent(MISAPPLIEDNAME_INDENT);
226
227 createMisappliedNameMenu();
228
229 compositeType = MISAPPLIED_NAME;
230 }
231
232 setDirty(true);
233 managedForm.getForm().layout();
234 }
235
236 /**
237 * Override of Composite.setData() which passes data along to
238 * DescriptionElementComposite's TextViewer where appropriate.
239 *
240 * @see org.eclipse.swt.widgets.Widget#setData(java.lang.Object)
241 */
242 public void setData(Object data) {
243 super.setData(data);
244 if (data instanceof TaxonBase) {
245
246 String text = CdmUtil.getDisplayName((TaxonBase) data);
247 getTextViewer().getTextWidget().setText(text);
248
249 if (getTextViewer() instanceof NameViewer) {
250 ((NameViewer) getTextViewer()).setCursorToEOL();
251
252 if (((TaxonBase) data).getName() != null) {
253 boolean hasProblem = ((TaxonBase) data).getName()
254 .getHasProblem();
255 ((NameViewer) getTextViewer()).setShowError(hasProblem);
256 }
257 }
258 }
259 }
260
261 /* (non-Javadoc)
262 * @see eu.etaxonomy.taxeditor.editor.name.EditorGroupedComposite#setSelection()
263 */
264 protected void setSelection() {
265 if (getData() instanceof TaxonBase) {
266 TaxonNameBase taxonBaseName = ((TaxonBase) getData()).getName();
267 managedForm.setInput(taxonBaseName);
268 } else {
269 super.setSelection();
270 }
271 }
272
273 private NameViewer createNameViewer() {
274 final NameViewer nameViewer = new NameViewer(this);
275
276 nameViewer.setLineBreakListener(new LineBreakListener() {
277
278 @Override
279 public void handleSplitText(String text) {
280
281 Composite parent = getParent();
282 final Composite grandParent = parent.getParent();
283
284 new CreateNewHeterotypicCompositeAction(text, managedForm)
285 .run();
286
287 // setDirty(true);
288 }
289
290 });
291 nameViewer.setParseListener(new ParseListener() {
292
293 @Override
294 public void parse(String text) {
295
296 TaxonBase taxonBase = (TaxonBase) getData();
297
298 NonViralName nonViralName = (NonViralName) taxonBase.getName();
299 if (nonViralName != null) {
300 // CdmUtil.parseFullName(nonViralName, text, null, true);
301 CdmUtil.parseFullReference(nonViralName, text, null, true);
302
303 nameViewer.setShowError(nonViralName.getHasProblem());
304 }
305
306 setDirty(true);
307 }
308 });
309
310 nameViewer.getTextWidget().addFocusListener(new FocusAdapter() {
311 public void focusGained(FocusEvent e) {
312 setFocus();
313 }
314 });
315
316 // createLineWrapSupport(nameViewer);
317
318 this.textViewer = nameViewer;
319
320 nameViewer.getTextWidget().setBackground(TaxEditorPlugin.getDefault().
321 getColor(ITaxEditorConstants.GROUP_GRAY_BKG_COLOR));
322
323 return nameViewer;
324 }
325
326 /**
327 * @param nameComposite
328 */
329 private void createSynonymMenu() {
330
331 if (!(getData() instanceof Synonym)) {
332 return;
333 }
334
335 Synonym synonym = (Synonym) getData();
336 ContextMenu contextMenu = createContextMenu();
337
338 Action misappliedNameAction = new MoveCompositeToMisappliedCompositeAction(
339 this, managedForm);
340 contextMenu.addAction(misappliedNameAction);
341
342 Action deleteSynonymAction = new DeleteSynonymCompositeAction(this,
343 getTaxon());
344 contextMenu.addAction(deleteSynonymAction);
345
346 contextMenu.addSeparator();
347
348 final Action addBasionymAction = new AddBasionymCompositeAction(this);
349 contextMenu.addAction(addBasionymAction);
350
351 final Action removeBasionymAction = new RemoveBasionymCompositeAction(
352 this);
353 contextMenu.addAction(removeBasionymAction);
354
355 addBasionymAction
356 .addPropertyChangeListener(new IPropertyChangeListener() {
357 @Override
358 public void propertyChange(
359 org.eclipse.jface.util.PropertyChangeEvent event) {
360 if (event.getProperty().equals(
361 ITaxEditorConstants.BASIONYM)) {
362 removeBasionymAction.setEnabled(true);
363 transform(NameComposite.ADD_GROUP_BASIONYM);
364 }
365 }
366 });
367
368 removeBasionymAction
369 .addPropertyChangeListener(new IPropertyChangeListener() {
370 @Override
371 public void propertyChange(
372 org.eclipse.jface.util.PropertyChangeEvent event) {
373 if (event.getProperty().equals(
374 ITaxEditorConstants.BASIONYM)) {
375 addBasionymAction.setEnabled(true);
376 transform(NameComposite.REMOVE_GROUP_BASIONYM);
377 }
378 }
379 });
380
381 contextMenu.addSeparator();
382
383 Action changeToThisTaxon = new ChangeSynonymToTaxonUiAction(synonym,
384 getTaxon());
385 contextMenu.addAction(changeToThisTaxon);
386
387 Action changeToNewAccepted = new ChangeCompositeToNewTaxonAction(this,
388 getTaxon());
389 contextMenu.addAction(changeToNewAccepted);
390 }
391
392 /**
393 * @param nameComposite
394 */
395 private void createAcceptedMenu() {
396
397 ContextMenu contextMenu = createContextMenu();
398
399 // TODO Make action "Create autonym and subspecies"
400
401 Action changeTaxonAction = new ChangeTaxonToSynonymAction(getTaxon());
402 contextMenu.addAction(changeTaxonAction);
403
404 Action moveTaxonAction = new MoveTaxonDialogAction(getTaxon());
405 contextMenu.addAction(moveTaxonAction);
406 }
407
408 /**
409 * @param nameComposite
410 */
411 private void createMisappliedNameMenu() {
412
413 ContextMenu contextMenu = createContextMenu();
414
415 Action deleteMisappliedNameAction = new DeleteMisappliedNameCompositeAction(
416 this, getTaxon());
417 contextMenu.addAction(deleteMisappliedNameAction);
418 }
419
420 /**
421 * The hierarchy of the DescriptionElementComposite should always be:
422 * <p>
423 * --------> DescriptionElementComposite.getData() -> Taxon or Synonym
424 * <p>
425 * --------> DescriptionElementComposite.getParent().getData() -> HomotypicalGroup or <br>
426 * -------->
427 * DescriptionElementComposite.getParent().getData(ITaxEditorConstants.MISAPPLIED_NAME) !=
428 * null
429 * <p>
430 * --------> DescriptionElementComposite.getParent().getParent().getData() -> Taxon
431 * <p>
432 * An error will be returned if this is not the case.
433 *
434 * @return
435 */
436 private Taxon getTaxon() {
437 Composite parent = getParent();
438 Composite grandParent = parent.getParent();
439 if (grandParent != null) {
440 Object parentData = grandParent.getData();
441 if (parentData instanceof Taxon) {
442 return (Taxon) parentData;
443 }
444 }
445 throw new IllegalArgumentException(
446 "The parent of the DescriptionElementComposite's parent does not have a Taxon in its data field as required.");
447 }
448
449 public boolean setParent(Composite parent) {
450
451 if (super.setParent(parent)) {
452
453 // Has this been moved to the misapplied names group?
454 if (parent.getData(ITaxEditorConstants.MISAPPLIED_NAME) != null) {
455 new ChangeCompositeToMisappliedNameAction(this, managedForm)
456 .run();
457 }
458
459 // Has this been moved to a HomotypicalGroup?
460 if (parent.getData() instanceof HomotypicalGroup) {
461 new AdaptCompositeToGroupAction(this,
462 (EditorGroupComposite) parent).run();
463 }
464 return true;
465
466 }
467 return false;
468 }
469
470 }