Nothing works.
[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.commands.operations.IUndoContext;
17 import org.eclipse.core.commands.operations.IUndoableOperation;
18 import org.eclipse.core.runtime.Assert;
19 import org.eclipse.jface.action.Action;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.custom.StyledText;
22 import org.eclipse.swt.events.DisposeEvent;
23 import org.eclipse.swt.events.DisposeListener;
24 import org.eclipse.swt.events.FocusAdapter;
25 import org.eclipse.swt.events.FocusEvent;
26 import org.eclipse.swt.events.KeyAdapter;
27 import org.eclipse.swt.events.KeyEvent;
28 import org.eclipse.swt.events.KeyListener;
29 import org.eclipse.swt.graphics.Font;
30 import org.eclipse.swt.graphics.Image;
31 import org.eclipse.swt.layout.FillLayout;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.widgets.Composite;
34 import org.eclipse.ui.forms.IManagedForm;
35 import org.eclipse.ui.forms.widgets.TableWrapData;
36 import org.eclipse.ui.views.properties.IPropertySource;
37
38 import eu.etaxonomy.cdm.model.name.BotanicalName;
39 import eu.etaxonomy.cdm.model.name.NonViralName;
40 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
41 import eu.etaxonomy.cdm.model.name.ZoologicalName;
42 import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
43 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
44 import eu.etaxonomy.taxeditor.ITaxEditorConstants;
45 import eu.etaxonomy.taxeditor.TaxEditorPlugin;
46 import eu.etaxonomy.taxeditor.controller.EditorController;
47 import eu.etaxonomy.taxeditor.controller.GlobalController;
48 import eu.etaxonomy.taxeditor.editor.GroupedComposite;
49 import eu.etaxonomy.taxeditor.editor.LineBreakListener;
50 import eu.etaxonomy.taxeditor.editor.ParseListener;
51 import eu.etaxonomy.taxeditor.model.CdmUtil;
52 import eu.etaxonomy.taxeditor.operations.name.CreateSynonymInNewGroupOperation;
53 import eu.etaxonomy.taxeditor.propertysheet.name.BotanicalNamePropertySource;
54 import eu.etaxonomy.taxeditor.propertysheet.name.NonViralNamePropertySource;
55 import eu.etaxonomy.taxeditor.propertysheet.name.ZoologicalNamePropertySource;
56
57 /**
58 * Formats an <code>GroupedComposite</code> to display <code>TaxonNameBase</code> elements
59 * in a <code>NameViewer</code>.
60 *
61 * @author p.ciardelli
62 * @created 02.06.2008
63 * @version 1.0
64 */
65 public abstract class NameComposite extends GroupedComposite {
66 private static final Logger logger = Logger.getLogger(NameComposite.class);
67
68 /**
69 * ************ COMPOSITE TYPES ************
70 */
71 public String compositeType;
72 public static final String ACCEPTED_TAXON = "accepted_name_composite";
73 public static final String HOMOTYPIC_SYNONYM = "homotypic_name_composite";
74 public static final String HETEROTYPIC_SYNONYM = "heterotypic_name_composite";
75 public static final String MISAPPLIED_NAME = "misappliedname_name_composite";
76 public static final String CONCEPTRELATION = "concept_name_comcposite";
77
78 /**
79 * ************ INDENTATIONS ************
80 */
81 public static final int ACCEPTED_INDENT = 0;
82 public static final int SYNONYM_INDENT = 15;
83 public static final int MISAPPLIEDNAME_INDENT = 15;
84 public static final int CONCEPT_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 public static final Font CONCEPT_FONT = TaxEditorPlugin.getDefault()
96 .getFont(ITaxEditorConstants.CONCEPT_FONT);
97
98 /**
99 * ************ ICONS ************
100 */
101 public static final Image ACCEPTED_ICON = TaxEditorPlugin.getDefault()
102 .getImage(ITaxEditorConstants.BLACK_SQUARE_ICON);
103 public static final Image HOMOTYPIC_SYNONYM_ICON = TaxEditorPlugin
104 .getDefault().getImage(ITaxEditorConstants.HOMOTYPIC_SYN_ICON);
105 public static final Image HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON = TaxEditorPlugin
106 .getDefault().getImage(
107 ITaxEditorConstants.HOMOTYPIC_SYN_ORIGINAL_ICON);
108 public static final Image HETEROTYPIC_SYNONYM_ICON = TaxEditorPlugin
109 .getDefault().getImage(ITaxEditorConstants.HETEROTYPIC_SYN_ICON);
110 public static final Image HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON = TaxEditorPlugin
111 .getDefault().getImage(
112 ITaxEditorConstants.HETEROTYPIC_SYN_ORIGINAL_ICON);
113 public static final Image MISAPPLIEDNAME_ICON = TaxEditorPlugin
114 .getDefault().getImage(ITaxEditorConstants.MISAPPLIED_NAME_ICON);
115 public static final Image CONCEPT_ICON = TaxEditorPlugin
116 .getDefault().getImage(ITaxEditorConstants.CONCEPT_ICON);
117 public static final Image AUTONYM_ICON = TaxEditorPlugin.getDefault()
118 .getImage(ITaxEditorConstants.AUTONYM_ICON);
119 public static final Image BASIONYM_ICON = TaxEditorPlugin.getDefault()
120 .getImage(ITaxEditorConstants.BASIONYM_ICON);
121 public static final Image MOVE = TaxEditorPlugin.getDefault().getImage(
122 ITaxEditorConstants.MOVE_ICON);
123
124 /**
125 * ************ TRANSFORMATIONS ************
126 */
127 public static final String ADD_GROUP_BASIONYM = "add_group_basionym";
128 public static final String REMOVE_GROUP_BASIONYM = "remove_group_basionym";
129
130 /**
131 * ************ MENU ACTIONS ************
132 */
133 public Action CHANGE_TAXON_TO_SYNONYM_ACTION;
134
135 private static final String EMPTY_NAME_PROMPT = "Click to add name";
136
137 /**
138 * Used to turn parser on and off.
139 *
140 * @see activateParser
141 * @see deactivateParser
142 */
143 private boolean isUseParser = false;
144
145 protected boolean isParsing;
146
147 protected NameViewer nameViewer;
148
149 /**
150 * The constructor for a DescriptionElementComposite. Takes a parent Composite on which to
151 * create itself, and an IManagedForm for Composite life cycle methods, i.e.
152 * drawing borders, creating other Composites, creating line wrap support,
153 * etc.
154 *
155 * @param parent
156 * @param managedForm
157 */
158 public NameComposite(Composite parent, IManagedForm managedForm,
159 String compositeType, TaxonBase taxonBase) {
160 super(parent, managedForm);
161
162 createNameViewer();
163 createBorderSupport();
164 createLineWrapSupport();
165
166 // setData(taxonBase);
167
168 createParser();
169 createEmptyViewerPrompt(EMPTY_NAME_PROMPT);
170 setFocus();
171
172 // NOTE: placing this after setFocus() inexplicably solved a strange bug where if the first action
173 // during a session was to open a new taxon, the empty name prompt didn't work
174 createNameListener(taxonBase.getName());
175 }
176
177 protected String getEmptyTextPrompt() {
178 return EMPTY_NAME_PROMPT;
179 }
180
181 /**
182 * Listens for changes to this name's <code>fullTitleCache</code>.
183 *
184 * @param data
185 */
186 private void createNameListener(final TaxonNameBase name) {
187
188 if (name == null) {
189 return;
190 }
191
192 final PropertyChangeListener listener = new PropertyChangeListener() {
193 public void propertyChange(PropertyChangeEvent evt) {
194
195 if (isParsing) {
196 return;
197 }
198
199 if (EditorController.isSaving()) {
200 return;
201 }
202
203 deactivateParser();
204 ((NameViewer) getTextViewer()).setText(name.getFullTitleCache());
205 activateParser();
206 }
207 };
208
209 // TODO clean this part up
210 name.addPropertyChangeListener("fullTitleCache", listener);
211 name.addPropertyChangeListener("nomenclaturalMicroReference", listener);
212
213 // name.addPropertyChangeListener(ITaxEditorConstants.REFRESH_NAMEVIEWER, listener);
214
215 StrictReferenceBase reference = (StrictReferenceBase) name.getNomenclaturalReference();
216 if (reference != null) {
217 reference.addPropertyChangeListener("titleCache", listener);
218 }
219 }
220
221 protected void initNameViewer(TaxonBase taxonBase) {
222 String text = CdmUtil.getDisplayNameWithRef(taxonBase);
223 if (text.length() == 0) {
224 initEmptyText();
225 } else {
226 getTextViewer().getTextWidget().setText(text);
227
228 if (getTextViewer() instanceof NameViewer) {
229
230 ((NameViewer) getTextViewer()).setCursorToEOL();
231
232 TaxonNameBase name = taxonBase.getName();
233 if (name != null) {
234
235 // boolean hasProblem = name.getHasProblem();
236 // ((NameViewer) getTextViewer()).setShowError(name);
237
238 calculateErrors();
239 }
240 }
241 }
242 activateParser();
243 }
244
245 private void createParser() {
246 ((NameViewer) getTextViewer()).addParseListener(new ParseListener() {
247
248 @Override
249 public void parse(String text) {
250
251 // Either composite is not yet fully built, or
252 // the property sheet is writing to it
253 if (!isUseParser) {
254 return;
255 }
256
257 // Let others know the parser is active
258 isParsing = true;
259
260 // Get the name from the composite's data field
261 // TaxonBase taxonBase = (TaxonBase) getData();
262 // NonViralName nonViralName = (NonViralName) taxonBase.getName();
263
264 // Parse the name and paint the text field w any errors
265 if (getName() != null) {
266 CdmParserController.parseFullReference((NonViralName) getName(), text);
267 // ((NameViewer) getTextViewer()).setShowError(nonViralName);
268 }
269
270 // Any entry of text means the taxon has been changed
271 setDirty(true);
272
273 // The parser is no longer active
274 isParsing = false;
275
276 // Manually refresh the property sheet to reflect changes
277 setSelection();
278
279 // Show any errors in the name viewer
280 calculateErrors();
281 }
282 });
283 }
284
285 public void activateParser() {
286 isUseParser = true;
287 }
288
289 public void deactivateParser() {
290 isUseParser = false;
291 }
292
293 protected abstract TaxonNameBase getName();
294
295 protected void calculateErrors() {
296
297 nameViewer.clearErrors();
298
299 // if (getData() instanceof TaxonBase) {
300 // TaxonBase taxonBase = (TaxonBase) getData();
301 //
302 // TaxonNameBase name = taxonBase.getName();
303 // nameViewer.setShowParsingError(name);
304 // }
305 nameViewer.setShowParsingError(getName());
306
307 }
308
309 private NameViewer createNameViewer() {
310
311 viewerComposite = new Composite(this, SWT.NONE);
312 viewerComposite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE));
313 viewerComposite.setLayout(new FillLayout());
314
315 nameViewer = new NameViewer(viewerComposite);
316 StyledText styledText = nameViewer.getTextWidget();
317 // nameViewer.setLineBreakListener(new LineBreakListener() {
318
319 setTextViewer(nameViewer);
320
321 nameViewer.addLineBreakListener(new LineBreakListener() {
322
323 @Override
324 public void handleSplitText(String text) {
325
326 // Create a synonym in a new homotypic group using text as name
327 IUndoContext undoContext = EditorController.getUndoContext(taxon);
328 // IUndoableOperation operation = new CreateSynonymInNewGroupOperation
329 setOperation(new CreateSynonymInNewGroupOperation
330 ("new heterotypic synonym", undoContext, taxon, text)); //$NON-NLS-1$
331
332 // GlobalController.executeOperation(operation);
333
334 // getTextViewer().removeLineBreakListener(this);
335 }
336
337 });
338
339 styledText.addKeyListener(new KeyAdapter(){
340
341 @Override
342 public void keyReleased(KeyEvent e) {
343 if (operation != null) {
344 GlobalController.executeOperation(operation);
345 operation = null;
346 }
347 }
348
349 });
350
351 styledText.addFocusListener(new FocusAdapter() {
352 public void focusGained(FocusEvent e) {
353 setFocus();
354 }
355 });
356
357 // createLineWrapSupport(nameViewer);
358
359 styledText.setBackground(TaxEditorPlugin.getDefault().
360 getColor(ITaxEditorConstants.GROUP_GRAY_BKG_COLOR));
361
362 return nameViewer;
363 }
364
365
366 IUndoableOperation operation;
367
368 private Composite viewerComposite;
369
370 protected void setOperation(IUndoableOperation operation) {
371 this.operation = operation;
372 }
373
374 public void setText(String text) {
375 Assert.isNotNull(getTextViewer(),
376 "Cannot set text for a TextViewer that has not yet been initialized.");
377 Assert.isNotNull(getTextViewer().getDocument(),
378 "Cannot set text for a TextViewer whose Document has not yet been initialized.");
379 getTextViewer().getDocument().set(text);
380 }
381
382 public NameViewer getTextViewer() {
383 return this.nameViewer;
384 }
385
386 public void setTextViewer(NameViewer textViewer) {
387 this.nameViewer = textViewer;
388 }
389
390 public void createBorderSupport() {
391 super.createBorderSupport();
392 if (viewerComposite != null) {
393 borderDecorator.setBorderedComposite(viewerComposite);
394 }
395 }
396
397
398 protected IPropertySource getPropertySourceByName(TaxonNameBase name) {
399 if (name == null) {
400 return null;
401 }
402
403 if (name.getClass() == BotanicalName.class) {
404 return new BotanicalNamePropertySource((BotanicalName) name);
405 }
406 if (name.getClass() == ZoologicalName.class) {
407 return new ZoologicalNamePropertySource((ZoologicalName) name);
408 }
409 if (name instanceof NonViralName) {
410 return new NonViralNamePropertySource((NonViralName) name);
411 }
412
413 return null;
414 }
415 }