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