adapt master to develop
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / view / derivate / DerivateView.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 package eu.etaxonomy.taxeditor.editor.view.derivate;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.EnumSet;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Set;
21 import java.util.UUID;
22
23 import javax.annotation.PostConstruct;
24 import javax.annotation.PreDestroy;
25 import javax.inject.Inject;
26 import javax.inject.Named;
27
28 import org.eclipse.core.commands.ExecutionException;
29 import org.eclipse.core.commands.operations.IOperationHistory;
30 import org.eclipse.core.runtime.IAdaptable;
31 import org.eclipse.core.runtime.IProgressMonitor;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.core.runtime.NullProgressMonitor;
34 import org.eclipse.core.runtime.Status;
35 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
36 import org.eclipse.e4.core.contexts.IEclipseContext;
37 import org.eclipse.e4.core.di.annotations.Optional;
38 import org.eclipse.e4.core.services.events.IEventBroker;
39 import org.eclipse.e4.ui.di.Focus;
40 import org.eclipse.e4.ui.di.Persist;
41 import org.eclipse.e4.ui.model.application.ui.MDirtyable;
42 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
43 import org.eclipse.e4.ui.services.EMenuService;
44 import org.eclipse.e4.ui.services.IServiceConstants;
45 import org.eclipse.e4.ui.workbench.modeling.EPartService;
46 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
47 import org.eclipse.jface.util.LocalSelectionTransfer;
48 import org.eclipse.jface.viewers.ISelectionChangedListener;
49 import org.eclipse.jface.viewers.IStructuredSelection;
50 import org.eclipse.jface.viewers.StructuredSelection;
51 import org.eclipse.jface.viewers.TreeNode;
52 import org.eclipse.jface.viewers.TreeSelection;
53 import org.eclipse.jface.viewers.TreeViewer;
54 import org.eclipse.jface.viewers.Viewer;
55 import org.eclipse.jface.viewers.ViewerComparator;
56 import org.eclipse.swt.SWT;
57 import org.eclipse.swt.dnd.DND;
58 import org.eclipse.swt.dnd.Transfer;
59 import org.eclipse.swt.layout.GridData;
60 import org.eclipse.swt.layout.GridLayout;
61 import org.eclipse.swt.widgets.Composite;
62 import org.eclipse.swt.widgets.Tree;
63 import org.eclipse.ui.IMemento;
64 import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
65
66 import eu.etaxonomy.cdm.api.filter.TaxonOccurrenceRelationType;
67 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
68 import eu.etaxonomy.cdm.api.service.ITaxonService;
69 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
70 import eu.etaxonomy.cdm.model.molecular.SingleRead;
71 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
72 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
73 import eu.etaxonomy.cdm.model.taxon.Taxon;
74 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
75 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
76 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
77 import eu.etaxonomy.taxeditor.editor.EditorUtil;
78 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
79 import eu.etaxonomy.taxeditor.editor.name.e4.TaxonEditor;
80 import eu.etaxonomy.taxeditor.editor.view.derivate.searchFilter.DerivateSearchCompositeController;
81 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
82 import eu.etaxonomy.taxeditor.model.AbstractUtility;
83 import eu.etaxonomy.taxeditor.model.IContextListener;
84 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
85 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
86 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
87 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
88 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
89 import eu.etaxonomy.taxeditor.model.MessagingUtils;
90 import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
91 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
92 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
93 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
94 import eu.etaxonomy.taxeditor.store.CdmStore;
95 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
96 import eu.etaxonomy.taxeditor.view.search.derivative.DerivateContentProvider;
97 import eu.etaxonomy.taxeditor.view.search.derivative.DerivateLabelProvider;
98 import eu.etaxonomy.taxeditor.workbench.part.ICollapsableExpandable;
99 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
100
101 /**
102 * Displays the derivate hierarchy of the specimen specified in the editor input.
103 */
104 public class DerivateView implements IPartContentHasFactualData,
105 ICdmEntitySessionEnabled<SpecimenOrObservationBase<?>>, IDirtyMarkable, IPostOperationEnabled, IPartContentHasDetails, IPartContentHasSupplementalData, IPartContentHasMedia,
106 IContextListener, IE4SavablePart, ICollapsableExpandable {
107
108 private static final String SPECIMEN_EDITOR = Messages.DerivateView_SPECIMEN_EDITOR;
109
110 public static final String ID = "eu.etaxonomy.taxeditor.editor.view.derivate.DerivateView"; //$NON-NLS-1$
111 public static final String INPUT_ID = ID+".editorInput"; //$NON-NLS-1$
112
113 public static final String YOU_NEED_TO_SAVE_BEFORE_PERFORMING_THIS_ACTION = Messages.DerivateView_YOU_NEED_TO_SAVE;
114 public static final String VIEW_HAS_UNSAVED_CHANGES = Messages.DerivateView_UNSAVED_CHANGES;
115
116 private static final List<String> SPECIMEN_INIT_STRATEGY = Arrays.asList(new String[] {
117 "descriptions", //$NON-NLS-1$
118 "annotations", //$NON-NLS-1$
119 "markers", //$NON-NLS-1$
120 "credits", //$NON-NLS-1$
121 "extensions", //$NON-NLS-1$
122 "rights", //$NON-NLS-1$
123 "sources", //$NON-NLS-1$
124 "derivationEvents.derivatives.annotations", //$NON-NLS-1$
125 "derivationEvents.derivatives.markers", //$NON-NLS-1$
126 "derivationEvents.derivatives.credits", //$NON-NLS-1$
127 "derivationEvents.derivatives.extensions", //$NON-NLS-1$
128 "derivationEvents.derivatives.rights", //$NON-NLS-1$
129 "derivationEvents.derivatives.sources" //$NON-NLS-1$
130 });
131
132 private static final int WARN_THRESHOLD = 200;
133
134 private TreeViewer viewer;
135
136 private final int dndOperations = DND.DROP_MOVE;
137
138 private DerivateLabelProvider labelProvider;
139
140 private DerivateContentProvider contentProvider;
141
142 private DerivateSearchCompositeController derivateSearchCompositeController;
143
144 @Inject
145 private IEventBroker eventBroker;
146
147 /**
148 * A map with keys being the derivative entities belonging to the {@link UUID}s passed to the constructor
149 * and values being the root elements of the hierarchy (may be the same objects as the derivative entities)
150 */
151 private Map<SpecimenOrObservationBase<?>, SpecimenOrObservationBase<?>> derivateToRootEntityMap;
152
153 /**
154 * The set of root elements
155 */
156 private Set<SpecimenOrObservationBase<?>> rootElements;
157
158 private ICdmEntitySession cdmEntitySession;
159
160 /**
161 * <code>true</code> if this view is listening to selection changes
162 */
163 private boolean listenToSelectionChange;
164
165 private Taxon selectedTaxon;
166
167 @Inject
168 private ESelectionService selService;
169
170 @Inject
171 private MDirtyable dirty;
172
173 private ISelectionChangedListener selectionChangedListener;
174
175 private Set<AbstractPostOperation> operations = new HashSet<>();
176
177 @Inject
178 private MPart thisPart;
179
180 /**
181 * Default constructor
182 */
183 @Inject
184 public DerivateView() {
185 }
186
187 public void init(DerivateViewEditorInput editorInput){
188 this.derivateToRootEntityMap = new HashMap<>();
189 this.rootElements = new HashSet<>();
190
191 //init tree
192 Collection<UUID> derivativeUuids = editorInput.getDerivativeUuids();
193 checkWarnThreshold(derivativeUuids);
194 updateRootEntities(derivativeUuids);
195 //set taxon filter
196 derivateSearchCompositeController.setTaxonFilter(editorInput.getTaxonUuid());
197 //reset status bar
198 //TODO e4
199 // getEditorSite().getActionBars().getStatusLineManager().setMessage(""); //$NON-NLS-1$
200 }
201
202 @PostConstruct
203 public void createPartControl(Composite parent, EMenuService menuService,
204 IEclipseContext context) {
205 if (CdmStore.isActive()){
206 if(cdmEntitySession == null){
207 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
208 }
209 }
210 else{
211 return;
212 }
213 //listen to context changes
214 CdmStore.getContextManager().addContextListener(this);
215
216 parent.setLayout(new GridLayout());
217
218 //---search and filter---
219 derivateSearchCompositeController = new DerivateSearchCompositeController(parent, this);
220 GridData gridDataSearchBar = new GridData();
221 gridDataSearchBar.horizontalAlignment = GridData.FILL;
222 gridDataSearchBar.grabExcessHorizontalSpace = true;
223 derivateSearchCompositeController.setLayoutData(gridDataSearchBar);
224 derivateSearchCompositeController.setEnabled(CdmStore.isActive());
225
226 //---tree viewer---
227 viewer = new TreeViewer(new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
228 GridData gridDataTree = new GridData();
229 gridDataTree.horizontalAlignment = GridData.FILL;
230 gridDataTree.verticalAlignment = GridData.FILL;
231 gridDataTree.grabExcessVerticalSpace = true;
232 gridDataTree.grabExcessHorizontalSpace = true;
233 viewer.getTree().setLayoutData(gridDataTree);
234 contentProvider = new DerivateContentProvider();
235 viewer.setContentProvider(contentProvider);
236 labelProvider = new DerivateLabelProvider();
237
238 viewer.setLabelProvider(labelProvider);
239 viewer.getTree().setEnabled(CdmStore.isActive());
240
241 //propagate selection
242 selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
243 viewer.addSelectionChangedListener(selectionChangedListener);
244
245 //create context menu
246 menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.editor.popupmenu.specimeneditor");
247
248 //add drag'n'drop support
249 Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
250 viewer.addDragSupport(dndOperations, transfers, new DerivateDragListener(this));
251 DerivateDropListener dropListener = new DerivateDropListener(this);
252 ContextInjectionFactory.inject(dropListener, context);
253 viewer.addDropSupport(dndOperations, transfers, dropListener);
254 }
255
256 public void updateRootEntities() {
257 updateRootEntities((Collection)null);
258 }
259
260 public void updateRootEntities(Collection<UUID> derivativeUuids) {
261
262 /*
263 * If the active session is not the session of the Derivative Editor
264 * then we will save the active session for later, bind temporarily
265 * to our session and rebind to the original session when we are
266 * done. This happens e.g. if a selection change happens in the
267 * taxon editor and "Link with editor" is enabled. The selection
268 * change event and thus the loading in updateRootEntities() happens
269 * in the session of the taxon editor.
270 */
271 ICdmEntitySession previousCdmEntitySession = CdmStore.getCurrentSessionManager().getActiveSession();
272 if(cdmEntitySession != null) {
273 cdmEntitySession.bind();
274 }
275 eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
276 List<SpecimenOrObservationBase> derivates = null;
277 if(derivativeUuids!=null){
278 this.derivateToRootEntityMap = new HashMap<>();
279 this.rootElements = new HashSet<>();
280 derivates = CdmStore.getService(IOccurrenceService.class).load(new ArrayList(derivativeUuids), SPECIMEN_INIT_STRATEGY);
281 }
282 updateRootEntities(derivates);
283 if(previousCdmEntitySession!=null){
284 previousCdmEntitySession.bind();
285 }
286
287 }
288
289 public void updateRootEntities(List<SpecimenOrObservationBase> derivates) {
290 if(derivates!=null){
291 eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, null);
292 this.derivateToRootEntityMap = new HashMap<>();
293 this.rootElements = new HashSet<>();
294 for (SpecimenOrObservationBase<?> derivate : derivates) {
295
296 if(derivate instanceof FieldUnit){
297 derivateToRootEntityMap.put(derivate, derivate);
298 }
299 else {
300 SpecimenOrObservationBase<?> topMostDerivate = EditorUtil.getTopMostDerivate(derivate);
301 if(topMostDerivate!=null){
302 derivateToRootEntityMap.put(derivate, topMostDerivate);
303 }
304 else{
305 derivateToRootEntityMap.put(derivate, derivate);
306 }
307 }
308 }
309 for (SpecimenOrObservationBase<?> specimen : derivateToRootEntityMap.values()) {
310 rootElements.add(specimen);
311 }
312 }
313 labelProvider.updateLabelCache(rootElements);
314 viewer.setInput(rootElements);
315 viewer.setComparator(new ViewerComparator() {
316 @Override
317 public int compare(Viewer testViewer, Object e1, Object e2) {
318 if (((TreeNode)e1).getValue() instanceof SpecimenOrObservationBase){
319 return ((SpecimenOrObservationBase)((TreeNode)e1).getValue()).getTitleCache().compareTo(((SpecimenOrObservationBase)((TreeNode)e2).getValue()).getTitleCache());
320 }else{
321 return e1.toString().compareTo(e2.toString());
322 }
323 //return (((SpecimenOrObservationBase) e1).getTitleCache()).compareTo(((SpecimenOrObservationBase) e2).getTitleCache());
324 }
325 });
326
327 //TODO e4
328 // getEditorSite().getActionBars().getStatusLineManager().setMessage(String.format(Messages.DerivateView_CNT_DERIVATIVES_FOUND, rootElements.size()));
329
330 //set selection to derivatives if the filter criteria
331 //taxon assignment or derivative type are set
332 if(derivates!=null && !derivateSearchCompositeController.isDefaultSearch()){
333 List<TreeNode> nodesToSelect = new ArrayList<>();
334 for (SpecimenOrObservationBase<?> specimenOrObservationBase : derivates) {
335 nodesToSelect.add(new TreeNode(specimenOrObservationBase));
336 }
337 setSelection(new StructuredSelection(nodesToSelect));
338 }
339 else{
340 setSelection(null);
341 }
342 }
343
344 private void setSelection(StructuredSelection selection){
345 viewer.removeSelectionChangedListener(selectionChangedListener);
346 viewer.setSelection(selection);
347 viewer.addSelectionChangedListener(selectionChangedListener);
348 }
349
350 public void updateLabelCache(){
351 labelProvider.updateLabelCache(rootElements);
352 }
353
354 @Persist
355 @Override
356 public void save(IProgressMonitor monitor) {
357 String taskName = Messages.DerivateView_SAVING_HIERARCHY;
358 monitor.beginTask(taskName, 3);
359
360 if (!cdmEntitySession.isActive()){
361 cdmEntitySession.bind();
362 }
363
364 monitor.worked(1);
365
366 for(AbstractPostOperation entry:operations){
367 IStatus status = Status.CANCEL_STATUS;
368 final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
369 .getUIInfoAdapter(AbstractUtility.getShell());
370 String operationlabel = entry.getLabel();
371 try {
372 entry.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
373 status = entry.execute(new NullProgressMonitor(), uiInfoAdapter);
374 } catch (ExecutionException e) {
375
376 MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
377
378 }
379
380 String statusString = status.equals(Status.OK_STATUS) ? "completed"
381 : "cancelled";
382
383 IPostOperationEnabled postOperationEnabled = entry
384 .getPostOperationEnabled();
385 if (postOperationEnabled != null) {
386 postOperationEnabled.onComplete();
387 }
388
389
390 //AbstractUtility.executeOperation(entry,sync);
391 }
392
393 operations.clear();
394 CdmStore.getService(IOccurrenceService.class).merge(new ArrayList<>(rootElements), true);
395
396 monitor.worked(1);
397
398 this.setDirty(false);
399 monitor.worked(1);
400 monitor.done();
401 dirty.setDirty(false);
402 refreshTree();
403 }
404
405 /**
406 * @param isDirty the isDirty to set
407 */
408 public void setDirty(boolean isDirty) {
409 dirty.setDirty(isDirty);
410 }
411
412 public Set<AbstractPostOperation> getOperations() {
413 return operations;
414 }
415
416 public void addOperation(AbstractPostOperation operation) {
417 this.operations.add(operation);
418 }
419
420 @Focus
421 public void setFocus() {
422 //make sure to bind again if maybe in another view the session was unbound
423
424 if(cdmEntitySession != null) {
425 cdmEntitySession.bind();
426 }
427 if(viewer!=null && !viewer.getControl().isDisposed()) {
428 viewer.getControl().setFocus();
429 selService.setSelection(viewer.getSelection());
430 }
431 }
432
433 @Override
434 public void changed(Object element) {
435 setDirty(true);
436 viewer.update(new TreeNode(element), null);
437 viewer.refresh();
438 }
439
440 @Override
441 public void forceDirty() {
442 changed(null);
443 }
444
445 @Override
446 public Map<Object, List<String>> getPropertyPathsMap() {
447 List<String> specimenPropertyPaths = Arrays.asList(new String[] {
448 "descriptions", //$NON-NLS-1$
449 "derivationEvents.derivates", //$NON-NLS-1$
450 "annotations", //$NON-NLS-1$
451 "markers", //$NON-NLS-1$
452 "credits", //$NON-NLS-1$
453 "extensions", //$NON-NLS-1$
454 "rights", //$NON-NLS-1$
455 "sources" //$NON-NLS-1$
456 });
457 Map<Object, List<String>> specimenPropertyPathMap =
458 new HashMap<>();
459 specimenPropertyPathMap.put(SpecimenOrObservationBase.class,specimenPropertyPaths);
460 return specimenPropertyPathMap;
461 }
462
463 /**
464 * Refreshes the derivate hierarchy tree and expands the tree
465 * to show and select the given object.
466 *
467 * @param expandTo the object to which the tree should be expanded
468 */
469 public void refreshTree(Object expandTo){
470 refreshTree();
471 TreeSelection selection = (TreeSelection) viewer.getSelection();
472 viewer.expandToLevel(selection.getFirstElement(), 1);
473 viewer.setSelection(new StructuredSelection(new TreeNode(expandTo)));
474 }
475
476 /**
477 * Refreshes the derivate hierarchy tree
478 */
479 public void refreshTree(){
480 if(!viewer.getTree().isDisposed()){
481 viewer.refresh();
482 }
483 }
484
485 //FIXME:Remoting hack to make this work for remoting
486 //This should actually be resolved using remoting post operations
487 public void remove(Object obj) {
488 if (obj instanceof TreeNode){
489 obj = ((TreeNode)obj).getValue();
490 }
491 rootElements.remove(obj);
492 this.derivateToRootEntityMap.remove(obj);
493 viewer.setInput(rootElements);
494 }
495
496 /**
497 * @return a set of {@link SingleRead}s that have multiple parents
498 */
499 public Set<SingleRead> getMultiLinkSingleReads() {
500 return DerivateLabelProvider.getMultiLinkSingleReads();
501 }
502
503 public Object getSelectionInput() {
504 return selectedTaxon;
505 }
506
507 public DerivateLabelProvider getLabelProvider() {
508 return labelProvider;
509 }
510
511 @Override
512 public boolean postOperation(Object objectAffectedByOperation) {
513 refreshTree();
514 if(objectAffectedByOperation!=null){
515 changed(objectAffectedByOperation);
516 }
517 return true;
518 }
519
520 @Override
521 public boolean onComplete() {
522 return true;
523 }
524
525
526 @Override
527 public boolean canAttachMedia() {
528 return true;
529 }
530
531 public void addFieldUnit(FieldUnit fieldUnit) {
532 rootElements.add(fieldUnit);
533 derivateToRootEntityMap.put(fieldUnit, fieldUnit);
534 }
535
536 @Override
537 public ICdmEntitySession getCdmEntitySession() {
538 return cdmEntitySession;
539 }
540
541 @PreDestroy
542 public void dispose() {
543 if(cdmEntitySession != null) {
544 cdmEntitySession.dispose();
545 cdmEntitySession = null;
546 }
547 dirty.setDirty(false);
548 }
549
550
551 @Inject
552 @Optional
553 public void selectionChanged(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) IStructuredSelection selection,
554 @Named(IServiceConstants.ACTIVE_PART) MPart activePart, MPart thisPart){
555 if(activePart == thisPart || viewer==null){
556 return;
557 }
558 if(viewer.getTree().isDisposed()){
559 return;
560 }
561 if(listenToSelectionChange){
562 selectedTaxon = null;
563 if(activePart.getObject() instanceof TaxonEditor){
564 selectedTaxon = ((TaxonEditor) activePart.getObject()).getTaxon();
565 }
566 else if(selection != null){
567 Object selectedElement = selection.getFirstElement();
568 if(selectedElement instanceof TaxonNodeDto){
569 TaxonBase<?> taxonBase = CdmStore.getService(ITaxonService.class).load(((TaxonNodeDto)selectedElement).getTaxonUuid());
570 if(HibernateProxyHelper.isInstanceOf(taxonBase, Taxon.class)){
571 selectedTaxon = HibernateProxyHelper.deproxy(taxonBase, Taxon.class);
572 }
573 else if(selectedElement instanceof TaxonNode){
574 selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, TaxonNode.class).getTaxon();
575 }
576 else if(selectedElement instanceof Taxon){
577 selectedTaxon = HibernateProxyHelper.deproxy(selectedElement, Taxon.class);
578 }
579 }
580 }
581 if(selectedTaxon!=null){
582 boolean includeUnpublished = true;
583 EnumSet<TaxonOccurrenceRelationType> associationFilter = TaxonOccurrenceRelationType.All();
584 Collection<FieldUnit> fieldUnits = CdmStore.getService(IOccurrenceService.class)
585 .listRootUnitsByAssociatedTaxon(FieldUnit.class, selectedTaxon, includeUnpublished, associationFilter, null, null);
586 Collection<UUID> uuids = new HashSet<>();
587 for (SpecimenOrObservationBase<?> specimenOrObservationBase : fieldUnits) {
588 uuids.add(specimenOrObservationBase.getUuid());
589 }
590 checkWarnThreshold(uuids);
591 updateRootEntities(uuids);
592
593 thisPart.setLabel(SPECIMEN_EDITOR+": " + selectedTaxon.getName()); //$NON-NLS-1$
594 }
595 else{
596 updateRootEntities((Collection<UUID>)Collections.EMPTY_LIST);
597 }
598 }
599 }
600
601 private void checkWarnThreshold(Collection<UUID> uuids) {
602 if(uuids!=null && uuids.size()>WARN_THRESHOLD){
603 MessagingUtils.warningDialog(Messages.DerivateView_PERF_WARNING, this.getClass(), String.format(Messages.DerivateView_PERF_WARNING_MESSAGE, uuids.size()));
604 uuids.clear();
605 }
606 }
607
608 public TreeViewer getViewer() {
609 return viewer;
610 }
611
612 @Override
613 public List<SpecimenOrObservationBase<?>> getRootEntities() {
614 return new ArrayList<>(rootElements);
615 }
616
617 public void toggleListenToSelectionChange(MPart part) {
618 listenToSelectionChange = !listenToSelectionChange;
619 derivateSearchCompositeController.setEnabled(!listenToSelectionChange);
620 if(!listenToSelectionChange){
621 selectedTaxon = null;
622 part.setLabel(SPECIMEN_EDITOR);
623 }
624 else if(selectedTaxon==null){
625 part.setLabel(SPECIMEN_EDITOR+Messages.DerivateView_NO_TAXON_SELECTED);
626 }
627 }
628
629 public DerivateSearchCompositeController getSearchController() {
630 return derivateSearchCompositeController;
631 }
632
633 public boolean isListenToSelectionChange(){
634 return listenToSelectionChange;
635 }
636
637 @Override
638 public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
639 }
640
641 @Override
642 public void contextStop(IMemento memento, IProgressMonitor monitor) {
643 //close view when workbench closes
644 try{
645 thisPart.getContext().get(EPartService.class).hidePart(thisPart);
646 }
647 catch(Exception e){
648 //nothing
649 }
650 }
651
652 @Override
653 public void contextStart(IMemento memento, IProgressMonitor monitor) {
654 }
655
656 @Override
657 public void contextRefresh(IProgressMonitor monitor) {
658 }
659
660 @Override
661 public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
662 }
663
664 @Override
665 public boolean isDirty() {
666 return dirty.isDirty();
667 }
668
669 @Override
670 public void collapse() {
671 viewer.collapseAll();
672 }
673
674 @Override
675 public void expand() {
676 viewer.expandAll();
677 }
678 }