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