<CR> in name relation - select name now the same as clicking the "Search" button.
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / UiUtil.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;
11
12 import java.util.HashSet;
13 import java.util.Set;
14
15 import org.apache.log4j.Logger;
16 import org.eclipse.core.commands.operations.IOperationHistory;
17 import org.eclipse.core.commands.operations.IUndoContext;
18 import org.eclipse.core.commands.operations.OperationHistoryFactory;
19 import org.eclipse.jface.preference.IPreferenceStore;
20 import org.eclipse.swt.graphics.Color;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Display;
24 import org.eclipse.swt.widgets.Shell;
25 import org.eclipse.swt.widgets.Tree;
26 import org.eclipse.swt.widgets.TreeItem;
27 import org.eclipse.ui.IActionBars;
28 import org.eclipse.ui.IEditorInput;
29 import org.eclipse.ui.IEditorPart;
30 import org.eclipse.ui.IEditorReference;
31 import org.eclipse.ui.IPageLayout;
32 import org.eclipse.ui.IViewPart;
33 import org.eclipse.ui.IViewReference;
34 import org.eclipse.ui.IWorkbench;
35 import org.eclipse.ui.IWorkbenchPage;
36 import org.eclipse.ui.PartInitException;
37 import org.eclipse.ui.forms.IManagedForm;
38 import org.eclipse.ui.operations.IWorkbenchOperationSupport;
39 import org.eclipse.ui.views.properties.PropertySheet;
40 import org.eclipse.ui.views.properties.PropertySheetPage;
41
42 import eu.etaxonomy.cdm.model.description.Feature;
43 import eu.etaxonomy.cdm.model.name.BotanicalName;
44 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
45 import eu.etaxonomy.cdm.model.name.NonViralName;
46 import eu.etaxonomy.cdm.model.name.Rank;
47 import eu.etaxonomy.cdm.model.name.ZoologicalName;
48 import eu.etaxonomy.cdm.model.taxon.Taxon;
49 import eu.etaxonomy.taxeditor.editor.CompositeBorderDecorator;
50 import eu.etaxonomy.taxeditor.editor.EditorGroupComposite;
51 import eu.etaxonomy.taxeditor.editor.MultiPageTaxonEditor;
52 import eu.etaxonomy.taxeditor.editor.WarningAnnotation;
53 import eu.etaxonomy.taxeditor.model.CdmUtil;
54 import eu.etaxonomy.taxeditor.model.NameEditorInput;
55 import eu.etaxonomy.taxeditor.navigation.TaxonomicTreeView;
56 import eu.etaxonomy.taxeditor.navigation.TaxonomicTreeViewer;
57 import eu.etaxonomy.taxeditor.propertysheet.CustomSortPropertySheetEntry;
58
59 /**
60 * A collection of useful methods related to the UI.
61 *
62 * @author p.ciardelli
63 * @created 27.05.2008
64 * @version 1.0
65 */
66 public class UiUtil {
67 private static final Logger logger = Logger.getLogger(UiUtil.class);
68
69 private static Set<Feature> preferredFeatureSet;
70 private static Set<Rank> preferredRankSet;
71 private static IViewPart treeView;
72
73 public static IViewPart getPropertySheet() {
74 for (IViewReference reference : getActivePage().getViewReferences()) {
75 if (reference.getId().equals(IPageLayout.ID_PROP_SHEET)) {
76 return reference.getView(false);
77 }
78 }
79 return null;
80 }
81
82 /**
83 * By default, property sheet has buttons in the toolbar for
84 * "Show advanced properties" and "Show categories".
85 * <p>
86 * This is confusing for the user, hence a method to remove them
87 * until such time as advanced properties or categories are implemented.
88 */
89 public static void hidePropertySheetToolbar() {
90 PropertySheet propertySheet = (PropertySheet) getPropertySheet();
91 IActionBars actionBars = propertySheet.getViewSite().getActionBars();
92 actionBars.getToolBarManager().removeAll();
93 actionBars.getMenuManager().removeAll();
94 }
95
96 /**
97 * The property sheet listener ensures only property sheets
98 * with data cause the Property Sheet to be updated.
99 */
100 public static void addPropertySheetInputListener() {
101 IViewPart propertySheet = getPropertySheet();
102 // propertySheet.get
103 PropertySheet ps = (PropertySheet) propertySheet;
104 // ps.addPartPropertyListener(listener)
105 // ps.addPropertyListener(l)
106 }
107
108 /**
109 * @param input
110 * @return
111 * @throws PartInitException
112 */
113 public static IEditorPart getEditorByInput(IEditorInput input)
114 throws PartInitException {
115 for (IEditorReference reference : getActivePage().getEditorReferences()) {
116 if (reference.getEditorInput().equals(input)) {
117 IEditorPart editor = reference.getEditor(false);
118 return editor;
119 }
120 }
121 return null;
122 }
123
124 /**
125 * Returns a set of all currently open
126 * <code>MultiPageTaxonEditor</code>s.
127 *
128 * @return
129 */
130 public static Set<IEditorPart> getOpenTaxonEditors() {
131
132 Set<IEditorPart> taxonEditors = new HashSet<IEditorPart>();
133
134 for (IEditorReference reference : getActivePage().getEditorReferences()) {
135 IEditorPart editor = reference.getEditor(false);
136 if (editor instanceof MultiPageTaxonEditor) {
137 taxonEditors.add(editor);
138 }
139 }
140 return taxonEditors;
141 }
142
143 public static IEditorPart getEditorByTaxon(Taxon taxon)
144 throws PartInitException {
145 IEditorInput input = new NameEditorInput(taxon);
146 return getEditorByInput(input);
147 }
148
149 /**
150 * @return
151 */
152 public static IWorkbenchPage getActivePage() {
153 return TaxEditorPlugin.getDefault().getWorkbench()
154 .getActiveWorkbenchWindow().getActivePage();
155 }
156
157 /**
158 * @return
159 */
160 public static Shell getShell() {
161 return TaxEditorPlugin.getDefault().getWorkbench()
162 .getActiveWorkbenchWindow().getShell();
163 }
164
165 /**
166 * @param input
167 * @param editorId
168 * @throws PartInitException
169 */
170 public static void openEditor(IEditorInput input, String editorId)
171 throws PartInitException {
172 getActivePage().openEditor(input, editorId);
173 }
174
175 /**
176 * @param taxon
177 * @param save
178 * @throws PartInitException
179 */
180 public static void closeEditor(Taxon taxon, boolean save)
181 throws PartInitException {
182 IEditorPart editor = getEditorByTaxon(taxon);
183 closeEditor(editor, save);
184 }
185
186 /**
187 * @param input
188 * @param save
189 * @throws PartInitException
190 */
191 public static void closeEditor(IEditorInput input, boolean save)
192 throws PartInitException {
193 IEditorPart editor = getEditorByInput(input);
194 closeEditor(editor, save);
195 }
196
197 /**
198 * @param editor
199 * @param save
200 * @throws PartInitException
201 */
202 public static void closeEditor(IEditorPart editor, boolean save)
203 throws PartInitException {
204 if (editor != null) {
205 getActivePage().closeEditor(editor, save);
206 }
207 }
208
209 public static IViewPart getViewById(String id) {
210 return TaxEditorPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().
211 getActivePage().findView(id);
212 }
213
214
215 /**
216 * Returns the <code>TaxonomicTreeViewer</code> used for navigation. Not to
217 * be confused with the window that contains it, <code>TaxonomicTreeView</code>.
218 *
219 * @return
220 */
221 public static TaxonomicTreeViewer getTreeViewer() {
222 TaxonomicTreeView view = getTreeView();
223 if (view == null) {
224 return null;
225 }
226 return view.getTreeViewer();
227 }
228
229 /**
230 * @see eu.etaxonomy.taxeditor.navigation.TaxonomicTreeView#createTreeViewer()
231 *
232 * @return
233 */
234 public static TaxonomicTreeViewer createTreeViewer() {
235 TaxonomicTreeView view = getTreeView();
236 if (view == null) {
237 return null;
238 }
239 return view.createTreeViewer();
240 }
241
242 /**
243 * Returns the <code>TaxonomicTreeView</code> containing the
244 * <code>TaxonomicTreeViewer</code> used for navigation.
245 *
246 * @return
247 */
248 public static TaxonomicTreeView getTreeView() {
249 if (treeView == null) {
250 treeView = getViewById(TaxonomicTreeView.ID);
251 if (!(treeView instanceof TaxonomicTreeView)) {
252 treeView = null;
253 }
254 }
255 return (TaxonomicTreeView) treeView;
256 }
257
258
259 public static IWorkbenchOperationSupport getOperationSupport() {
260 IWorkbench workbench = TaxEditorPlugin.getDefault().getWorkbench();
261 return workbench.getOperationSupport();
262 }
263
264 public static IOperationHistory getOperationHistory() {
265 return OperationHistoryFactory.getOperationHistory();
266 // return getOperationSupport().getOperationHistory();
267 }
268
269 public static IUndoContext getWorkbenchUndoContext() {
270 return getOperationSupport().getUndoContext();
271 }
272
273 public static void doEditorSave(Taxon taxon, boolean confirm) {
274 IEditorPart editor = null;
275 try {
276 editor = getEditorByTaxon(taxon);
277 } catch (PartInitException e) {
278 // TODO Auto-generated catch block
279 e.printStackTrace();
280 }
281 if (editor != null) {
282 getActivePage().saveEditor(editor, confirm);
283 }
284 }
285
286
287 public static EditorGroupComposite getMisappliedNameGroupComposite(
288 IManagedForm managedForm) {
289
290 // Iterate through parent's children until we find a composite which has a data field
291 // for MISAPPLIED_NAME
292 Composite parent = managedForm.getForm().getBody();
293 for (Control groupComposite : parent.getChildren()) {
294 if (groupComposite instanceof EditorGroupComposite) {
295 if (groupComposite.getData(ITaxEditorConstants.MISAPPLIED_NAME) != null) {
296 return (EditorGroupComposite) groupComposite;
297 }
298 }
299 }
300 return null;
301 }
302
303 public static EditorGroupComposite createMisappliedNameGroupComposite(
304 IManagedForm managedForm) {
305
306 Composite parent = managedForm.getForm().getBody();
307
308 EditorGroupComposite composite = new EditorGroupComposite(parent, managedForm);
309 composite.setData(ITaxEditorConstants.MISAPPLIED_NAME,"");
310 new CompositeBorderDecorator(composite, managedForm);
311 return composite;
312 }
313
314 public static IPreferenceStore getPrefStore() {
315 return TaxEditorPlugin.getDefault().getPreferenceStore();
316 }
317
318 /**
319 * Returns a <code>Set</code> of the <code>Feature</code>s that the user has chosen
320 * to have shown in preferences.
321 * </p>
322 * <p>
323 * <code>Feature</code>s are shown unless otherwise specified.
324 * </p>
325 * @return
326 */
327 public static Set<Feature> getPreferredFeatures() {
328
329 // Initialize preferredFeatureSet as necessary
330 if (preferredFeatureSet == null) {
331
332 preferredFeatureSet = new HashSet<Feature>();
333
334 for (Feature feature : CdmUtil.getFeatures()) {
335
336 // If the feature is set to show, add it to preferredFeatureSet
337 if (getFeaturePreference(feature)) {
338 preferredFeatureSet.add(feature);
339 }
340 }
341
342 }
343 return preferredFeatureSet;
344 }
345
346 /**
347 * True if <code>Feature</code> is set to "show" in preferences.
348 *
349 * @param feature
350 * @return
351 */
352 public static boolean getFeaturePreference(Feature feature) {
353
354 String preferenceKey = getPreferenceKey(feature);
355
356 // If feature does not yet have a pref, set it to true
357 if (!getPrefStore().contains(preferenceKey)) {
358 getPrefStore().setDefault(preferenceKey, true);
359 }
360
361 return getPrefStore().getBoolean(preferenceKey);
362 }
363
364 /**
365 * Set the show state of a <code>Feature</code> in the
366 * <code>PreferenceStore</code>.
367 * <p>
368 * Also sets <code>preferredFeatureSet</code> to null to force it be
369 * re-populated the next time {@link #getPreferredFeatures()} is called.
370 *
371 * @param feature
372 * @param show
373 */
374 public static void setFeaturePreference(Feature feature, boolean show) {
375 preferredFeatureSet = null;
376 getPrefStore().setValue(getPreferenceKey(feature), show);
377 }
378
379 /**
380 * Construct a unique key using <code>Feature</code>'s <code>Uuid</code>
381 *
382 * @param feature
383 * @return
384 */
385 private static String getPreferenceKey(Feature feature) {
386 return ITaxEditorConstants.FEATURE_PREFERENCE
387 . concat(".")
388 . concat(feature.getUuid().toString());
389 }
390
391 /**
392 * Returns a <code>Set</code> of the <code>Rank</code>s that the user has chosen
393 * to have shown in preferences.
394 * </p>
395 * <p>
396 * <code>Rank</code>s are shown unless otherwise specified.
397 * </p>
398 * @return
399 */
400 public static Set<Rank> getPreferredRanks() {
401
402 // Initialize preferredFeatureSet as necessary
403 if (preferredRankSet == null) {
404
405 preferredRankSet = new HashSet<Rank>();
406
407 for (Rank rank : CdmUtil.getRanks()) {
408
409 // If the feature is set to show, add it to preferredFeatureSet
410 if (getRankPreference(rank)) {
411 preferredRankSet.add(rank);
412 }
413 }
414
415 }
416 return preferredRankSet;
417 }
418
419 /**
420 * True if <code>Rank</code> is set to "show" in preferences.
421 *
422 * @param rank
423 * @return
424 */
425 public static boolean getRankPreference(Rank rank) {
426
427 String preferenceKey = getPreferenceKey(rank);
428
429 // If rank does not yet have a pref, set it to true
430 if (!getPrefStore().contains(preferenceKey)) {
431 getPrefStore().setDefault(preferenceKey, true);
432 }
433
434 return getPrefStore().getBoolean(preferenceKey);
435 }
436
437 /**
438 * Set the show state of a <code>Rank</code> in the
439 * <code>PreferenceStore</code>.
440 * <p>
441 * Also sets <code>preferredRankSet</code> to null to force it be
442 * re-populated the next time {@link #getPreferredRanks()} is called.
443 *
444 * @param rank
445 * @param show
446 */
447 public static void setRankPreference(Rank rank, boolean show) {
448 preferredRankSet = null;
449 getPrefStore().setValue(getPreferenceKey(rank), show);
450
451 }
452
453 /**
454 * Construct a unique key using <code>Rank</code>'s <code>Uuid</code>
455 *
456 * @param feature
457 * @return
458 */
459 private static String getPreferenceKey(Rank rank) {
460 return ITaxEditorConstants.RANK_PREFERENCE
461 . concat(".")
462 . concat(rank.getUuid().toString());
463 }
464
465 /**
466 * @return
467 */
468 public static NonViralName getPreferredNameClassInstance() {
469 String nameCodePreference = TaxEditorPlugin.getDefault().getPreferenceStore().getString(ITaxEditorConstants.CODE_PREFERENCE);
470
471 // Check whether name code preference needs to be initialized
472 if (nameCodePreference == null || nameCodePreference.equals("")) {
473 nameCodePreference = ITaxEditorConstants.DEFAULT_CODE_PREFERENCE;
474 UiUtil.getPrefStore().setValue(ITaxEditorConstants.CODE_PREFERENCE,
475 nameCodePreference);
476 }
477
478 if (nameCodePreference.equals(ITaxEditorConstants.CODE_PREFERENCE_ICBN)) {
479 return BotanicalName.NewInstance(null);
480 } else if (nameCodePreference.equals(ITaxEditorConstants.CODE_PREFERENCE_ICZN)) {
481 return ZoologicalName.NewInstance(null);
482 }
483 return NonViralName.NewInstance(null);
484 }
485
486 public static String getNameCodePreference() {
487 String nameCodePreference = getPrefStore().getString(ITaxEditorConstants.CODE_PREFERENCE);
488
489 // Check whether name code preference needs to be initialized
490 if (nameCodePreference == null || nameCodePreference.equals("")) {
491 nameCodePreference = ITaxEditorConstants.DEFAULT_CODE_PREFERENCE;
492 getPrefStore().setValue(ITaxEditorConstants.CODE_PREFERENCE, nameCodePreference);
493 }
494
495 return nameCodePreference;
496 }
497
498 /**
499 * @return
500 */
501 public static NomenclaturalCode getPreferredNomenclaturalCode() {
502
503 String nameCodePreference = getNameCodePreference();
504
505 if (nameCodePreference.equals(ITaxEditorConstants.CODE_PREFERENCE_ICBN)) {
506 return NomenclaturalCode.ICBN();
507 } else if (nameCodePreference.equals(ITaxEditorConstants.CODE_PREFERENCE_ICZN)) {
508 return NomenclaturalCode.ICZN();
509 }
510 return null;
511 }
512
513 /**
514 * Appends the code (i.e. ICBN or ICZN) specified in the user preferences
515 * to a string. The result is separated by a period: "<code>key.ICBN</code>".
516 *
517 * @param key
518 * @return
519 */
520 public static String concatCodeMessageSuffix(String key) {
521 String code = getNameCodePreference();
522 return key + "." + code;
523 }
524
525 public static void setStatusMessage(String msg) {
526 getPropertySheet().getViewSite().getActionBars().getStatusLineManager().setMessage(msg);
527 }
528
529 public static void setPropertySheetTree(Tree tree) {
530 TaxEditorPlugin.getDefault().setPropertySheetTree(tree);
531 }
532
533 public static Tree getPropertySheetTree() {
534 return TaxEditorPlugin.getDefault().getPropertySheetTree();
535 }
536
537 public static void setPropertySheetPage(PropertySheetPage page) {
538 TaxEditorPlugin.getDefault().setPropertySheetPage(page);
539 }
540
541 public static PropertySheetPage getPropertySheetPage() {
542 return TaxEditorPlugin.getDefault().getPropertySheetPage();
543 }
544
545 /**
546 * UiUtil.paintPropertySheetRow(P_DATEPUBLISHED, new Color(Display.getDefault(), WarningAnnotation.WARNING_RGB), true);
547 * UiUtil.unpaintPropertySheetRow(P_DATEPUBLISHED);
548 *
549 * @param id
550 * @param color
551 * @param doPaintChildren
552 */
553 public static void paintPropertySheetRow(String id, Color color, boolean doPaintChildren) {
554
555 // Catch null property sheet name
556 if (id == null) {
557 return;
558 }
559
560 // Catch uninit'ed property sheet tree
561 if (getPropertySheetTree() == null) {
562 return;
563 }
564
565 paintPropertySheetRow(id, color, doPaintChildren, getPropertySheetTree());
566 }
567
568 private static void paintPropertySheetRow(String id, Color color, boolean doPaintChildren, Object treeOrItem) {
569
570 // Init items w zero-length array
571 TreeItem[] items = new TreeItem[]{};
572
573 // Get child items depending to class
574 if (treeOrItem instanceof Tree) {
575 items = ((Tree) treeOrItem).getItems();
576 }
577 if (treeOrItem instanceof TreeItem) {
578 items = ((TreeItem) treeOrItem).getItems();
579 }
580
581 // If array hasn't been populated by the above, return
582 if (items.length == 0) {
583 return;
584 }
585
586 // Prop. sheet id's take the form "01:xxxx" for sorting - truncate
587 id = CustomSortPropertySheetEntry.truncateDisplayName(id);
588
589 // Iterate through child items
590 for (TreeItem item : items) {
591
592 // Item found, paint it
593 if (id.equals(item.getText())) {
594 paintItem(item, color, doPaintChildren);
595 return;
596 }
597
598 // Recursively search for item to paint in child items
599 if (item.getItemCount() > 0) {
600 paintPropertySheetRow(id, color, doPaintChildren, item);
601 }
602 }
603 }
604
605 /**
606 * Note: children are only painted if submenu has already been created, i.e. opened once.
607 *
608 * @param item
609 * @param color
610 * @param doPaintChildren
611 */
612 private static void paintItem(TreeItem item, Color color, boolean doPaintChildren) {
613
614 // Paint the item
615 item.setBackground(color);
616
617 // Recursively paint child items if requested
618 if (doPaintChildren) {
619 for (TreeItem childItem : item.getItems()) {
620 paintItem(childItem, color, doPaintChildren);
621 }
622 }
623 }
624
625 public static void unpaintPropertySheetRow(String id) {
626
627 // Catch uninit'ed property sheet tree
628 if (getPropertySheetTree() == null) {
629 return;
630 }
631
632 // Get tree's background color to "unpaint"
633 Color color = getPropertySheetTree().getBackground();
634
635 paintPropertySheetRow(id, color, true);
636 }
637 }