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