p2izing the editor
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor.prototype2 / src / eu / etaxonomy / taxeditor / prototype2 / view / NameEditorView.java
1 package eu.etaxonomy.taxeditor.prototype2.view;
2
3 import java.beans.PropertyChangeEvent;
4 import java.beans.PropertyChangeListener;
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import org.eclipse.core.databinding.DataBindingContext;
9 import org.eclipse.core.databinding.beans.BeansObservables;
10 import org.eclipse.core.databinding.observable.set.ISetChangeListener;
11 import org.eclipse.core.databinding.observable.set.SetChangeEvent;
12 import org.eclipse.core.runtime.IProgressMonitor;
13 import org.eclipse.jface.text.source.SourceViewer;
14 import org.eclipse.swt.SWT;
15 import org.eclipse.swt.dnd.DND;
16 import org.eclipse.swt.dnd.DropTarget;
17 import org.eclipse.swt.dnd.DropTargetAdapter;
18 import org.eclipse.swt.dnd.DropTargetEvent;
19 import org.eclipse.swt.dnd.Transfer;
20 import org.eclipse.swt.events.FocusEvent;
21 import org.eclipse.swt.events.FocusListener;
22 import org.eclipse.swt.events.MouseEvent;
23 import org.eclipse.swt.events.MouseListener;
24 import org.eclipse.swt.events.SelectionAdapter;
25 import org.eclipse.swt.events.SelectionEvent;
26 import org.eclipse.swt.events.SelectionListener;
27 import org.eclipse.swt.graphics.Point;
28 import org.eclipse.swt.graphics.Rectangle;
29 import org.eclipse.swt.layout.FillLayout;
30 import org.eclipse.swt.layout.GridData;
31 import org.eclipse.swt.layout.GridLayout;
32 import org.eclipse.swt.widgets.Composite;
33 import org.eclipse.swt.widgets.CoolBar;
34 import org.eclipse.swt.widgets.CoolItem;
35 import org.eclipse.swt.widgets.Display;
36 import org.eclipse.swt.widgets.Event;
37 import org.eclipse.swt.widgets.Label;
38 import org.eclipse.swt.widgets.Link;
39 import org.eclipse.swt.widgets.Listener;
40 import org.eclipse.swt.widgets.Menu;
41 import org.eclipse.swt.widgets.MenuItem;
42 import org.eclipse.swt.widgets.ToolBar;
43 import org.eclipse.swt.widgets.ToolItem;
44 import org.eclipse.ui.IEditorInput;
45 import org.eclipse.ui.IEditorSite;
46 import org.eclipse.ui.PartInitException;
47 import org.eclipse.ui.part.EditorPart;
48 import org.eclipse.ui.part.WorkbenchPart;
49
50 import com.swtdesigner.ResourceManager;
51 import com.swtdesigner.SWTResourceManager;
52
53 import eu.etaxonomy.cdm.model.name.BotanicalName;
54 import eu.etaxonomy.cdm.model.name.Rank;
55 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
56 import eu.etaxonomy.cdm.model.taxon.Synonym;
57 import eu.etaxonomy.cdm.model.taxon.Taxon;
58 import eu.etaxonomy.taxeditor.prototype2.Activator;
59 import eu.etaxonomy.taxeditor.prototype2.controller.ActionDeleteTaxon;
60 import eu.etaxonomy.taxeditor.prototype2.controller.ActionOpenNameEditor;
61 import eu.etaxonomy.taxeditor.prototype2.controller.ActionOpenNewChildNameEditor;
62 import eu.etaxonomy.taxeditor.prototype2.controller.ActionSaveTaxon;
63 import eu.etaxonomy.taxeditor.prototype2.controller.TaxonTransfer;
64 import eu.etaxonomy.taxeditor.prototype2.model.PropertySheetNode;
65 import eu.etaxonomy.taxeditor.prototype2.view.nameviewersupport.GroupComposite;
66 import eu.etaxonomy.taxeditor.prototype2.view.nameviewersupport.NameComposite;
67 import eu.etaxonomy.taxeditor.prototype2.view.nameviewersupport.TesterooWritableSet;
68 import eu.etaxonomy.taxeditor.prototype2.view.propertysheetsupport.PropertySheetContentProvider;
69 import eu.etaxonomy.taxeditor.prototype2.view.propertysheetsupport.PropertySheetValueEditingSupport;
70 import eu.etaxonomy.taxeditor.prototype2.view.propertysheetsupport.PropertySheetValueLabelProvider;
71
72 /**
73 * TODO: user should always know what kind of name - BotanicalName,
74 * ZoologicalName, etc. - he will be editing when a new taxon
75 * is created
76 *
77 * @author p.ciardelli
78 *
79 */
80 public class NameEditorView extends EditorPart {
81 /**
82 * The taxon the editor is editing
83 */
84 private Taxon taxon;
85 /**
86 * The higher taxon of the taxon the editor is editing
87 */
88 private Taxon higherTaxon = null;
89 /**
90 * Shared listener that sets dirty state to true
91 * when any registered property changes
92 */
93 private PropertyChangeListener taxonChangeListener = new PropertyChangeListener() {
94 public void propertyChange(PropertyChangeEvent arg0) {
95 dirty = true;
96 firePropertyChange(PROP_DIRTY);
97 }
98 };
99 /**
100 * Arrays for the creation of synonyms - text and images
101 */
102 String [] relTypes = {"a synonym (type unknown)",
103 "a homotypic synonym",
104 "a heterotypic synoynm",
105 "a basionym",
106 "a replaced synonym",
107 "a homonym",
108 "an orthographic variant",
109 "a misapplied name",
110 "a concept relation"};
111 String [] relImgs = {"unknown_no_bg.gif",
112 "homosyn_no_bg.gif",
113 "heterosyn_no_bg.gif",
114 "basionym_no_bg.gif",
115 "repsyn_no_bg.gif",
116 "homonym_no_bg.gif",
117 "orthovariant_no_bg.gif",
118 "misapplied_no_bg.gif",
119 "concept_no_bg.gif"};
120 String [] conceptTypes = {"congruent","included in","includes","overlaps","excludes","doubtful"};
121 /**
122 * If true, show "save" prompt before closing editor
123 */
124 public boolean dirty = false;
125 String clickText;
126
127 private Composite nameComposite;
128 private Composite contentComposite;
129
130 private PropertySheetViewer propertySheetViewer;
131 private Composite parent;
132
133 public static final String ID = "eu.etaxonomy.taxeditor.prototype2.view.nameeditorview"; //$NON-NLS-1$
134
135 public NameEditorView() {
136
137 }
138 /**
139 * Create contents of the editor part
140 * @param parent
141 */
142 @Override
143 public void createPartControl(Composite parent) {
144
145 this.parent = parent;
146 parent.setLayout(new GridLayout());
147 parent.setRedraw(true);
148
149
150 createHigherTaxon();
151
152
153 final CoolBar coolBar = new CoolBar(parent, SWT.NONE);
154 new CoolItem(coolBar, SWT.PUSH).setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/save_edit.gif"));
155
156 final ToolBar toolBar = new ToolBar(parent, SWT.NONE);
157 // toolBar.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
158
159 final ToolItem itemSave = new ToolItem(toolBar, SWT.PUSH);
160 itemSave.setToolTipText("Save taxon");
161 itemSave.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/save_edit.gif"));
162 itemSave.addSelectionListener(new SelectionListener() {
163 public void widgetDefaultSelected(SelectionEvent e) {
164 dirty = false;
165 new ActionSaveTaxon(taxon).run();
166 }
167 public void widgetSelected(SelectionEvent e) {
168 dirty = false;
169 new ActionSaveTaxon(taxon).run();
170 }
171 });
172
173 final ToolItem itemMove = new ToolItem(toolBar, SWT.DROP_DOWN);
174 itemMove.setToolTipText("Move taxon");
175
176 final Menu menuMove = new Menu(toolBar);
177 addDropDown(itemMove, menuMove);
178
179 final MenuItem moveTaxonMenuItem = new MenuItem(menuMove, SWT.NONE);
180 moveTaxonMenuItem.setText("Move taxon to another higher taxon");
181 moveTaxonMenuItem.addSelectionListener(new SelectionAdapter() {
182 public void widgetSelected(final SelectionEvent e) {
183 new MoveDialogView(getSite().getShell());
184 MoveDialogView dialog = new MoveDialogView(getSite().getShell());
185 dialog.open(taxon);
186 }
187 });
188
189 final MenuItem taxonToSynonymMenuItem = new MenuItem(menuMove, SWT.NONE);
190 taxonToSynonymMenuItem.setSelection(true);
191 taxonToSynonymMenuItem.setText("Turn taxon's accepted name into a synonym");
192 taxonToSynonymMenuItem.addSelectionListener(new SelectionAdapter() {
193 public void widgetSelected(final SelectionEvent e) {
194 new MoveDialogView(getSite().getShell());
195 MoveDialogView dialog = new MoveDialogView(getSite().getShell());
196 dialog.open(taxon);
197 }
198 });
199
200 itemMove.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/correction_change.gif"));
201
202 final ToolItem itemDelete = new ToolItem(toolBar, SWT.NONE);
203 itemDelete.setToolTipText("Delete taxon");
204 itemDelete.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/delete_edit.gif"));
205 itemDelete.addSelectionListener(new SelectionListener() {
206
207 public void widgetDefaultSelected(SelectionEvent e) {
208 // TODO Auto-generated method stub
209
210 }
211 public void widgetSelected(SelectionEvent e) {
212 new ActionDeleteTaxon(taxon).run();
213 }
214 });
215
216 new ToolItem(toolBar, SWT.SEPARATOR);
217
218 final ToolItem itemAddRelationship = new ToolItem(toolBar, SWT.DROP_DOWN);
219 itemAddRelationship.setToolTipText("Add nom. or tax. relation to taxon");
220 itemAddRelationship.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/rel_no_bg.gif"));
221
222 /*
223 * Create menu to add relations to the taxon
224 */
225 final Menu menuAddRel = new Menu(toolBar);
226 addDropDown(itemAddRelationship, menuAddRel);
227
228 for (int i = 0; i < relTypes.length; i++) {
229 final MenuItem menuItem;
230 if (relTypes[i].contains("concept")) {
231 menuItem = new MenuItem(menuAddRel, SWT.CASCADE);
232
233 final Menu conceptMenu = new Menu(menuItem);
234 menuItem.setMenu(conceptMenu);
235
236 for (int j = 0; j < conceptTypes.length; j++) {
237 final MenuItem conceptMenuItem = new MenuItem(conceptMenu, SWT.CHECK);
238 conceptMenuItem.setText(conceptTypes[j]);
239 }
240 } else {
241 menuItem = new MenuItem(menuAddRel, SWT.NONE);
242 }
243
244 menuItem.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/" + relImgs[i]));
245 menuItem.setText("Add " + relTypes[i]);
246 }
247
248 new ToolItem(toolBar, SWT.SEPARATOR);
249
250 final ToolItem itemAddTaxon = new ToolItem(toolBar, SWT.DROP_DOWN);
251 itemAddTaxon.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/add_edit.gif"));
252 itemAddTaxon.setToolTipText("Add new taxon");
253
254 /*
255 * drop-down to add new "included in" taxon
256 */
257 final Menu menuAdd = new Menu(toolBar);
258 addDropDown(itemAddTaxon, menuAdd);
259
260 if (higherTaxon != null) {
261 final MenuItem addToHigherTaxonItem = new MenuItem(menuAdd, SWT.NONE);
262 addToHigherTaxonItem.setText("Add new taxon to \"" + higherTaxon.getName().getTitleCache() + "\"");
263 addToHigherTaxonItem.addSelectionListener(new SelectionListener() {
264 public void widgetDefaultSelected(SelectionEvent e) {
265 // TODO Auto-generated method stub
266
267 }
268 public void widgetSelected(SelectionEvent e) {
269 new ActionOpenNewChildNameEditor(higherTaxon).run();
270 }
271 });
272 }
273 final MenuItem addTaxonItem = new MenuItem(menuAdd, SWT.NONE);
274 addTaxonItem.setText("Add new taxon to this taxon");
275 addTaxonItem.addSelectionListener(new SelectionListener() {
276 public void widgetDefaultSelected(SelectionEvent e) {
277 // TODO Auto-generated method stub
278
279 }
280 public void widgetSelected(SelectionEvent e) {
281 new ActionOpenNewChildNameEditor(taxon).run();
282 }
283 });
284
285 contentComposite = new Composite(parent, SWT.NONE);
286 contentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
287 contentComposite.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
288 final GridLayout gridLayout_2 = new GridLayout();
289 gridLayout_2.marginHeight = 0;
290 gridLayout_2.marginWidth = 0;
291 gridLayout_2.numColumns = 2;
292 contentComposite.setLayout(gridLayout_2);
293 contentComposite.setRedraw(true);
294
295
296 nameComposite = new Composite(contentComposite, SWT.NONE);
297 nameComposite.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
298 nameComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true));
299 GridLayout gridLayout = new GridLayout();
300 gridLayout.verticalSpacing = 10;
301 nameComposite.setLayout(gridLayout);
302 nameComposite.setRedraw(true);
303
304
305 // clickText = "Click here to start entering accepted name or enter its individual fields in the property sheet to the right";
306 // NameViewer_ acceptedNameViewer = new AcceptedNameViewer(taxon, bindingContext, nameComposite);
307 // acceptedNameViewer.setBindingContext(bindingContext);
308 // acceptedNameViewer.configure(new NameViewerConfig());
309
310 GroupComposite homoGroupComposite = new GroupComposite(nameComposite);
311 homoGroupComposite.setTaxon(taxon);
312 homoGroupComposite.setNameEditorView(this);
313
314 new NameComposite(homoGroupComposite, taxon).setNameEditorView(this);
315
316 TesterooWritableSet.getInstance().addSetChangeListener
317 (new ISetChangeListener() {
318 public void handleSetChange(SetChangeEvent event) {
319 for ( Object addition: event.diff.getAdditions()) {
320 if (addition instanceof Synonym)
321 createHeterotypicalGroup((Synonym) addition);
322 }
323 nameComposite.layout();
324 contentComposite.layout();
325 }
326 });
327
328 // Listen for names being dragged outside of existing homotypic groups -
329 // user wants to create a new group
330 // Drop functionality
331 Transfer[] types = new Transfer[] {TaxonTransfer.getInstance()};
332 int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
333 DropTarget target = new DropTarget(nameComposite, operations);
334 target.setTransfer(types);
335 target.addDropListener(dropTargetAdapter);
336
337 /*
338 * construct PropertySheetViewer, with bindings to model layer
339 */
340 propertySheetViewer = new PropertySheetViewer(contentComposite);
341
342 propertySheetViewer.setContentProvider(
343 new PropertySheetContentProvider());
344 propertySheetViewer.getPropertyValueColumn().setLabelProvider(
345 new PropertySheetValueLabelProvider(propertySheetViewer));
346 propertySheetViewer.getPropertyValueColumn().setEditingSupport(
347 new PropertySheetValueEditingSupport(propertySheetViewer));
348
349 setPropertySheetNodes(taxon.getName());
350 }
351
352 /**
353 * Display hyperlinked higher taxon, if there is one
354 */
355 private void createHigherTaxon() {
356 Composite higherTaxonComposite = new Composite(parent, SWT.NONE);
357 higherTaxonComposite.setLayout(new FillLayout());
358 (new Label(higherTaxonComposite, SWT.NONE)).setText("Higher taxon: ");
359 if (higherTaxon == null)
360 (new Label(higherTaxonComposite, SWT.NONE)).setText("none");
361 else {
362 Link higherTaxonLink = new Link(higherTaxonComposite, SWT.NONE);
363 higherTaxonLink.setText("<a href=\"#\">" + higherTaxon.getName().getTitleCache() + "</a>");
364 higherTaxonLink.addMouseListener(new MouseListener() {
365 public void mouseDoubleClick(MouseEvent e) {
366 new ActionOpenNameEditor(higherTaxon).run();
367 }
368 public void mouseDown(MouseEvent e) {
369 new ActionOpenNameEditor(higherTaxon).run();
370 }
371 public void mouseUp(MouseEvent e) {
372 }
373 });
374 }
375 }
376 public void setPropertySheetNodes(TaxonNameBase taxonname) {
377 propertySheetViewer.setInput(getPropertySheetNodes(taxonname));
378 propertySheetViewer.setExpandedState(fullTitleNode, true);
379 }
380
381 private SourceViewer createAcceptedName_() {
382
383 // Method[] methods = BotanicalName.class.getMethods();
384 // for (int i = 0; i < methods.length; i++) {
385 // System.out.println("Annotations:");
386 // for (int j = 0; i < methods[j].getAnnotations().length; j++)
387 // System.out.println("\t" + methods[i].getAnnotations()[j]);
388 // System.out.println("Type: " + methods[i].getReturnType().toString());
389 // System.out.println("Name:" + methods[i].getName());
390 // System.out.println();
391 // }
392 // use annotations to find persistent methods
393
394
395 // PropertyDescriptor descriptor;
396 // try {
397 // descriptor = new PropertyDescriptor("genus", taxonname.getClass());
398 // try {
399 // System.out.println("Property desc. test in createAcceptedName: "
400 // + descriptor.getReadMethod().invoke(taxonname, null));
401 // } catch (IllegalArgumentException e) {
402 // // TODO Auto-generated catch block
403 // e.printStackTrace();
404 // } catch (IllegalAccessException e) {
405 // // TODO Auto-generated catch block
406 // e.printStackTrace();
407 // } catch (InvocationTargetException e) {
408 // // TODO Auto-generated catch block
409 // e.printStackTrace();
410 // }
411 // } catch (IntrospectionException e) {
412 // // TODO Auto-generated catch block
413 // e.printStackTrace();
414 // }
415
416 final SourceViewer sourceViewer = new SourceViewer(nameComposite, null, 0); // createSourceViewer(taxon.getName());
417
418 sourceViewer.getTextWidget().setLayoutData(
419 new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
420 sourceViewer.getTextWidget().setFont(
421 SWTResourceManager.getFont("Georgia", 12, SWT.NONE));
422
423 /*
424 * if this is a new name, show text prompt to start entering data
425 */
426 if (taxon.getName().getNameCache() == null) {
427 clickText = "Click here to start entering accepted name or enter individual fields in the property sheet to the right";
428
429 sourceViewer.getTextWidget().setText(clickText);
430 sourceViewer.getTextWidget().setFont(SWTResourceManager.getFont("Georgia", 12, SWT.ITALIC));
431 sourceViewer.getTextWidget().setForeground(SWTResourceManager.getColor(192, 192, 192));
432 sourceViewer.getTextWidget().addFocusListener(new FocusListener() {
433 public void focusGained(FocusEvent e) {
434 if (!dirty) {
435 sourceViewer.getTextWidget().setText("");
436 sourceViewer.getTextWidget().setFont(SWTResourceManager.getFont("Georgia", 12, SWT.NONE));
437 sourceViewer.getTextWidget().setForeground(SWTResourceManager.getColor(0, 0, 0));
438 // dirty = true;
439 // firePropertyChange(PROP_DIRTY);
440 }
441 }
442 public void focusLost(FocusEvent e) {
443 if (sourceViewer.getTextWidget().getText() == "") {
444 sourceViewer.getTextWidget().setForeground(SWTResourceManager.getColor(192, 192, 192));
445 sourceViewer.getTextWidget().setText(clickText);
446 sourceViewer.getTextWidget().setFont(SWTResourceManager.getFont("Georgia", 12, SWT.ITALIC));
447 dirty = false;
448 } else {
449 dirty = true;
450 }
451 }
452 });
453 }
454
455 return sourceViewer;
456 }
457
458
459
460 /**
461 * Creates the drop-down menu next to every synonym for changing relationship type
462 *
463 * @param label
464 * @param name
465 */
466 // private void createRelationMenu(Control control, BotanicalName name) {
467 private void createRelationMenu(final Label label) {
468
469 final Menu menu = new Menu(label);
470 label.setMenu(menu);
471
472 // context menu usually only shows up w/ right menu click -
473 // this listener lets the left click activate it as well
474 label.addMouseListener(new MouseListener() {
475 public void mouseDown(MouseEvent e) {
476 menu.setVisible(true);
477 }
478 public void mouseDoubleClick(MouseEvent e) { }
479 public void mouseUp(MouseEvent e) { }
480 });
481
482 createRelationMenuItem(menu, "delete_edit.gif", "Delete synonym from this taxon");
483 createRelationMenuItem(menu, "correction_change.gif", "Move synonym to another taxon");
484
485 new MenuItem(menu, SWT.SEPARATOR);
486
487 for (int i= 0; i < relTypes.length; i++) {
488 final String relImg = relImgs[i];
489 String relText = "Turn this synonym into " + relTypes[i];
490 createRelationMenuItem(menu, relImg, relText).addSelectionListener(new SelectionListener() {
491 public void widgetDefaultSelected(SelectionEvent e) {
492 }
493 public void widgetSelected(SelectionEvent e) {
494 label.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/" + relImg));
495 }
496 });
497 }
498 }
499
500 private MenuItem createRelationMenuItem(Menu menu, String img, String text) {
501 final MenuItem menuItem = new MenuItem(menu, SWT.NONE);
502 menuItem.setImage(ResourceManager.getPluginImage(Activator.getDefault(), "icons/" + img));
503 menuItem.setText(text);
504 return menuItem;
505 }
506
507 @Override
508 public void setFocus() {
509 // Set the focus
510 }
511
512 @Override
513 public void doSave(IProgressMonitor monitor) {
514 // Do the Save operation
515 }
516
517 @Override
518 public void doSaveAs() {
519 // Do the Save As operation
520 }
521
522 @Override
523 public void init(IEditorSite site, IEditorInput input) throws PartInitException {
524
525 if (!(input instanceof IEditorInput))
526 throw new PartInitException(
527 "Invalid Input: Must be IFileEditorInput");
528
529 if (input.getAdapter(Taxon.class) != null) {
530 taxon = (Taxon) input.getAdapter(Taxon.class);
531 } else {
532
533 taxon = null;
534 }
535
536 // Get parent taxon
537 if (taxon.getTaxonomicParent() != null)
538 higherTaxon = taxon.getTaxonomicParent();
539
540 // Register listeners for any change in accepted name or set of relations
541 taxon.getName().addPropertyChangeListener("titleCache", taxonChangeListener);
542 taxon.addPropertyChangeListener("synonyms", taxonChangeListener);
543
544 setSite(site);
545 setInput(input);
546
547 }
548
549 PropertySheetNode fullTitleNode;
550 /**
551 * @param taxonName
552 * @return
553 */
554 private List<PropertySheetNode> getPropertySheetNodes(TaxonNameBase taxonName) {
555
556 BotanicalName botName = (BotanicalName) taxonName;
557
558 List<PropertySheetNode> propertySheetNodes = new ArrayList<PropertySheetNode>();
559 fullTitleNode = new PropertySheetNode("Full Title", BeansObservables.observeValue(botName, "titleCache"),
560 null, PropertySheetNode.EDITABLE);
561 propertySheetNodes.add(fullTitleNode);
562
563 // Note: only top-level nodes are "add"-ed - otherwise, they are
564 // instantiated with their parent node
565 if (botName.getRank() == null) botName.setRank(Rank.GENUS());
566 new PropertySheetNode("Rank", botName.getRank().getLabel(),
567 fullTitleNode, PropertySheetNode.NOT_EDITABLE);
568 new PropertySheetNode("Genus", BeansObservables.observeValue(botName, "uninomial"),
569 fullTitleNode, PropertySheetNode.EDITABLE);
570 new PropertySheetNode("Species Epithet", BeansObservables.observeValue(botName, "specificEpithet"),
571 fullTitleNode, PropertySheetNode.EDITABLE);
572
573 String author =
574 botName.getCombinationAuthorTeam() == null ? "" :
575 botName.getCombinationAuthorTeam().getTitleCache();
576 new PropertySheetNode("Author", author,
577 fullTitleNode, PropertySheetNode.NOT_EDITABLE);
578
579 return propertySheetNodes;
580 }
581
582 @Override
583 public boolean isDirty() {
584 return dirty;
585 }
586
587 @Override
588 public boolean isSaveAsAllowed() {
589 return false;
590 }
591
592 private static void addDropDown(final ToolItem item, final Menu menu) {
593 item.addListener(SWT.Selection, new Listener() {
594 public void handleEvent(Event event) {
595 if (event.detail == SWT.ARROW) {
596 Rectangle rect = item.getBounds();
597 Point pt = new Point(rect.x, rect.y + rect.height);
598 pt = item.getParent().toDisplay(pt);
599 menu.setLocation(pt.x, pt.y);
600 menu.setVisible(true);
601 }
602 }
603 });
604 }
605
606 private void createHeterotypicalGroup(Synonym heterosyn) {
607
608 GroupComposite heteroGroupComposite = new GroupComposite(nameComposite);
609 heteroGroupComposite.setTaxon(taxon);
610 heteroGroupComposite.setNameEditorView(this);
611
612 NameComposite nameComposite = new NameComposite(heteroGroupComposite, heterosyn, taxon);
613 nameComposite.setNameEditorView(this);
614 nameComposite.setFocus();
615 }
616
617 /**
618 * Creates a new homotypic group when a name composite is dropped outside of all existing
619 * homotypic groups
620 */
621 DropTargetAdapter dropTargetAdapter = new DropTargetAdapter() {
622
623 public void drop(DropTargetEvent event) {
624
625 Synonym synonym = (Synonym) event.data;
626
627 GroupComposite homotypicGroupComposite = new GroupComposite(nameComposite);
628 homotypicGroupComposite.setTaxon(taxon);
629 homotypicGroupComposite.setNameEditorView(NameEditorView.this);
630
631 new NameComposite(homotypicGroupComposite, synonym, taxon).setFocus();
632
633 NameEditorView.this.contentComposite.layout();
634 }
635 };
636 }