fixes #805 and started to work on #835
[taxeditor.git] / taxeditor-editor / src / main / java / 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.util.Set;
13
14 import org.eclipse.jface.action.Action;
15 import org.eclipse.swt.graphics.Font;
16 import org.eclipse.swt.graphics.Image;
17 import org.eclipse.swt.widgets.Composite;
18 import org.eclipse.ui.views.properties.IPropertySource;
19
20 import eu.etaxonomy.cdm.model.common.CdmBase;
21 import eu.etaxonomy.cdm.model.name.BotanicalName;
22 import eu.etaxonomy.cdm.model.name.NameRelationship;
23 import eu.etaxonomy.cdm.model.name.NonViralName;
24 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
25 import eu.etaxonomy.cdm.model.name.ZoologicalName;
26 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
27 import eu.etaxonomy.taxeditor.editor.AbstractTaxonEditor;
28 import eu.etaxonomy.taxeditor.editor.EditorUtil;
29 import eu.etaxonomy.taxeditor.editor.GroupedComposite;
30 import eu.etaxonomy.taxeditor.editor.labels.ILabelImageStrategy;
31 import eu.etaxonomy.taxeditor.editor.labels.LabelImageProvider;
32 import eu.etaxonomy.taxeditor.model.ImageResources;
33 import eu.etaxonomy.taxeditor.model.NameHelper;
34 import eu.etaxonomy.taxeditor.model.Resources;
35 import eu.etaxonomy.taxeditor.operations.CreateSynonymInNewGroupOperation;
36 import eu.etaxonomy.taxeditor.propertysheet.name.BotanicalNamePropertySource;
37 import eu.etaxonomy.taxeditor.propertysheet.name.NonViralNamePropertySource;
38 import eu.etaxonomy.taxeditor.propertysheet.name.ZoologicalNamePropertySource;
39
40 /**
41 * Formats an <code>GroupedComposite</code> to display <code>TaxonNameBase</code> elements
42 * in a <code>NameViewer</code>.
43 *
44 * @author p.ciardelli
45 * @created 02.06.2008
46 * @version 1.0
47 */
48 public abstract class NameComposite<T extends TaxonBase> extends GroupedComposite{
49
50 /**
51 * ************ COMPOSITE TYPES ************
52 */
53 public String compositeType;
54 public static final String ACCEPTED_TAXON = "accepted_name_composite";
55 public static final String HOMOTYPIC_SYNONYM = "homotypic_name_composite";
56 public static final String HETEROTYPIC_SYNONYM = "heterotypic_name_composite";
57 public static final String MISAPPLIED_NAME = "misappliedname_name_composite";
58 public static final String CONCEPTRELATION = "concept_name_comcposite";
59
60 /**
61 * ************ INDENTATIONS ************
62 */
63 public static final int ACCEPTED_INDENT = 0;
64 public static final int SYNONYM_INDENT = 15;
65 public static final int MISAPPLIEDNAME_INDENT = 15;
66 public static final int CONCEPT_INDENT = 15;
67
68 /**
69 * ************ FONTS ************
70 */
71 public static final Font ACCEPTED_FONT = Resources
72 .getFont(Resources.ACCEPTED_TAXON_FONT);
73 public static final Font SYNONYM_FONT = Resources
74 .getFont(Resources.SYNONYM_FONT);
75 public static final Font MISAPPLIEDNAME_FONT = Resources
76 .getFont(Resources.MISAPPLIEDNAME_FONT);
77 public static final Font CONCEPT_FONT = Resources
78 .getFont(Resources.CONCEPT_FONT);
79
80 /**
81 * ************ ICONS ************
82 */
83 public static final Image ACCEPTED_ICON = ImageResources
84 .getImage(ImageResources.BLACK_SQUARE_ICON);
85 public static final Image HOMOTYPIC_SYNONYM_ICON = ImageResources.getImage(ImageResources.HOMOTYPIC_SYN_ICON);
86 public static final Image HOMOTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON = ImageResources.getImage(
87 ImageResources.HOMOTYPIC_SYN_ORIGINAL_ICON);
88 public static final Image HETEROTYPIC_SYNONYM_ICON = ImageResources.getImage(ImageResources.HETEROTYPIC_SYN_ICON);
89 public static final Image HETEROTYPIC_SYNONYM_ORIGINAL_COMBINATION_ICON = ImageResources.getImage(
90 ImageResources.HETEROTYPIC_SYN_ORIGINAL_ICON);
91 public static final Image MISAPPLIEDNAME_ICON = ImageResources.getImage(ImageResources.MISAPPLIED_NAME_ICON);
92 public static final Image CONCEPT_ICON = ImageResources.getImage(ImageResources.CONCEPT_ICON);
93 public static final Image AUTONYM_ICON = ImageResources
94 .getImage(ImageResources.AUTONYM_ICON);
95 public static final Image MOVE = ImageResources.getImage(ImageResources.MOVE_ICON);
96
97 /**
98 * ************ TRANSFORMATIONS ************
99 */
100 public static final String ADD_GROUP_BASIONYM = "add_group_basionym";
101 public static final String REMOVE_GROUP_BASIONYM = "remove_group_basionym";
102
103 /**
104 * ************ MENU ACTIONS ************
105 */
106 public Action CHANGE_TAXON_TO_SYNONYM_ACTION;
107
108 private static final String EMPTY_NAME_PROMPT = "Click to add name";
109
110 /**
111 * Used to turn parser on and off.
112 *
113 * @see activateParser
114 * @see deactivateParser
115 */
116 private boolean isUseParser = false;
117
118 protected boolean isParsing;
119
120 /**
121 * Whether this NameComposite has unsaved changes
122 */
123 private boolean isDirty = false;
124
125 private T taxonBase;
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(AbstractTaxonEditor editor, Composite parent, T taxonBase) {
137 super(editor, parent);
138
139 this.taxonBase = taxonBase;
140
141 createTextViewer();
142 createBorderSupport();
143 createLineWrapSupport();
144 createLineBreakListener();
145
146 this.setMenu(editor.getMenu());
147
148 setDraggableControl(textViewer.getRulerControl());
149
150 createEmptyViewerPrompt(EMPTY_NAME_PROMPT);
151
152 initializeComposite();
153 createParser();
154 }
155
156 /**
157 * Initialize the composite specific code
158 *
159 */
160 protected abstract void initializeComposite();
161
162 protected String getEmptyTextPrompt() {
163 return EMPTY_NAME_PROMPT;
164 }
165
166 /**
167 *
168 */
169 private void showNameRelations() {
170 TaxonNameBase<?, ?> name = getName();
171 if (name == null) {
172 return;
173 }
174
175 ILabelImageStrategy strategy = LabelImageProvider.getLabelStrategy(name);
176 LabelImageProvider labelProvider = new LabelImageProvider(strategy);
177
178 Set<NameRelationship> nameRelations = name.getNameRelations();
179 if (nameRelations.size() == 0) {
180 return;
181 }
182 for (NameRelationship nameRelation : nameRelations) {
183 String typeLabel = null;
184 TaxonNameBase<?, ?> relatedName = null;
185
186 if (name.equals(nameRelation.getFromName())) {
187 typeLabel = labelProvider.getNameRelationTypeLabel(
188 nameRelation.getType());
189 relatedName = nameRelation.getToName();
190 } else {
191 typeLabel = labelProvider.getNameRelationTypeInverseLabel(
192 nameRelation.getType());
193 relatedName = nameRelation.getFromName();
194 }
195
196 setNonEditableInfo(typeLabel + " " + NameHelper.getDisplayName(relatedName));
197 }
198 }
199
200 protected void initTextViewer(TaxonBase<?> taxonBase) {
201
202 showNameRelations();
203
204 String text = NameHelper.getDisplayNameWithRef(taxonBase);
205
206 if (text.length() == 0) {
207 initEmptyText();
208 } else {
209 textViewer.getTextWidget().setText(text);
210 textViewer.setCursorToEOL();
211 }
212 calculateErrors();
213 activateParser();
214 }
215
216 protected void parse(String text) {
217
218 // Either composite is not yet fully built, or
219 // the property sheet is writing to it
220 if (!isUseParser) {
221 return;
222 }
223
224 // Let others know the parser is active
225 isParsing = true;
226
227 // Parse the name and paint the text field w any errors
228 if (getName() != null) {
229 // TODO change to HibernateProxyImpl.deproxy() once it is available
230 CdmParserController.parseFullReference(CdmBase.deproxy(getName(), NonViralName.class), text);
231 }
232
233 // Any entry of text means the taxon has been changed
234 setDirty();
235
236 // The parser is no longer active
237 isParsing = false;
238
239 // Manually refresh the property sheet to reflect changes
240 setSelection();
241
242 // Show any errors in the name viewer
243 calculateErrors();
244 }
245
246 private void activateParser() {
247 isUseParser = true;
248 }
249
250 // FIXME we do have a naming conflict here
251 protected abstract TaxonNameBase<?, ?> getName();
252
253 protected void calculateErrors() {
254 textViewer.clearErrors();
255 textViewer.setShowParsingError(getName());
256 }
257
258 protected void handleSplitText(String text) {
259 // Create a synonym in a new homotypic group using text as name
260 EditorUtil.executeOperation(new CreateSynonymInNewGroupOperation
261 ("New Heterotypic Synonym", editor.getUndoContext(), editor.getTaxon(), text, editor));
262 }
263
264 protected IPropertySource getPropertySourceByName(TaxonNameBase<?, ?> name) {
265 if (name == null) {
266 return null;
267 }
268
269 if (name.getClass() == BotanicalName.class) {
270 return new BotanicalNamePropertySource((BotanicalName) name);
271 }
272 if (name.getClass() == ZoologicalName.class) {
273 return new ZoologicalNamePropertySource((ZoologicalName) name);
274 }
275 if (name instanceof NonViralName) {
276 return new NonViralNamePropertySource((NonViralName<?>) name);
277 }
278
279 return null;
280 }
281
282 /* (non-Javadoc)
283 * @see eu.etaxonomy.taxeditor.editor.GroupedComposite#refresh()
284 */
285 @Override
286 public void refresh() {
287 super.refresh();
288 // initTextViewer((TaxonBase) getData());
289
290 // FIXME this is copied from initTextViewer().
291
292 showNameRelations();
293
294 String text = NameHelper.getDisplayNameWithRef((TaxonBase) getData());
295
296 if (text.length() == 0) {
297 initEmptyText();
298 } else {
299 textViewer.getTextWidget().setText(text);
300 // textViewer.setCursorToEOL();
301 }
302 // calculateErrors();
303 // activateParser();
304 }
305
306 public boolean isDirty(){
307 return isDirty;
308 }
309
310 protected void setDirty(){
311 // propagate to editor
312 super.setDirty(true);
313 // set the dirty state for this composite
314 isDirty = true;
315 }
316
317 /**
318 * @return the taxonBase
319 */
320 public T getTaxonBase() {
321 return taxonBase;
322 }
323 }