Project

General

Profile

Download (18.3 KB) Statistics
| Branch: | Tag: | Revision:
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.navigation.navigator.e4;
10

    
11
import java.util.ArrayList;
12
import java.util.Comparator;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Observable;
16
import java.util.Observer;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import javax.annotation.PostConstruct;
21
import javax.annotation.PreDestroy;
22
import javax.inject.Inject;
23

    
24
import org.eclipse.core.commands.operations.UndoContext;
25
import org.eclipse.core.runtime.IAdaptable;
26
import org.eclipse.core.runtime.IProgressMonitor;
27
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
28
import org.eclipse.e4.core.contexts.IEclipseContext;
29
import org.eclipse.e4.core.di.annotations.Optional;
30
import org.eclipse.e4.ui.di.Focus;
31
import org.eclipse.e4.ui.di.UIEventTopic;
32
import org.eclipse.e4.ui.di.UISynchronize;
33
import org.eclipse.e4.ui.model.application.MApplication;
34
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
35
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
36
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
37
import org.eclipse.e4.ui.model.application.ui.menu.impl.HandledToolItemImpl;
38
import org.eclipse.e4.ui.services.EMenuService;
39
import org.eclipse.e4.ui.workbench.modeling.EModelService;
40
import org.eclipse.e4.ui.workbench.modeling.EPartService;
41
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
42
import org.eclipse.jface.util.LocalSelectionTransfer;
43
import org.eclipse.jface.viewers.IElementComparer;
44
import org.eclipse.jface.viewers.ISelection;
45
import org.eclipse.jface.viewers.ISelectionChangedListener;
46
import org.eclipse.jface.viewers.IStructuredSelection;
47
import org.eclipse.jface.viewers.StructuredSelection;
48
import org.eclipse.jface.viewers.TreePath;
49
import org.eclipse.jface.viewers.TreeViewer;
50
import org.eclipse.swt.SWT;
51
import org.eclipse.swt.dnd.DND;
52
import org.eclipse.swt.dnd.Transfer;
53
import org.eclipse.swt.layout.FillLayout;
54
import org.eclipse.swt.widgets.Composite;
55
import org.eclipse.swt.widgets.Tree;
56
import org.eclipse.ui.IMemento;
57

    
58
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
59
import eu.etaxonomy.cdm.api.application.CdmChangeEvent;
60
import eu.etaxonomy.cdm.api.application.CdmChangeEvent.Action;
61
import eu.etaxonomy.cdm.api.application.ICdmChangeListener;
62
import eu.etaxonomy.cdm.api.service.IClassificationService;
63
import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
64
import eu.etaxonomy.cdm.model.common.CdmBase;
65
import eu.etaxonomy.cdm.model.common.ICdmBase;
66
import eu.etaxonomy.cdm.model.taxon.Classification;
67
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
68
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
69
import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
70
import eu.etaxonomy.taxeditor.editor.name.e4.TaxonNameEditorE4;
71
import eu.etaxonomy.taxeditor.event.EventUtility;
72
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
73
import eu.etaxonomy.taxeditor.model.AbstractUtility;
74
import eu.etaxonomy.taxeditor.model.IContextListener;
75
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
76
import eu.etaxonomy.taxeditor.navigation.AppModelId;
77
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
78
import eu.etaxonomy.taxeditor.navigation.l10n.Messages;
79
import eu.etaxonomy.taxeditor.navigation.navigator.EmptyRoot;
80
import eu.etaxonomy.taxeditor.navigation.navigator.Root;
81
import eu.etaxonomy.taxeditor.navigation.navigator.TaxonNodeNavigatorComparator;
82
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
83
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
84
import eu.etaxonomy.taxeditor.store.CdmStore;
85
import eu.etaxonomy.taxeditor.store.LoginManager;
86
import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
87
import eu.etaxonomy.taxeditor.workbench.part.ICollapsableExpandable;
88

    
89
/**
90
 * @author pplitzner
91
 * @since Sep 7, 2017
92
 */
93
public class TaxonNavigatorE4 implements
94
		IPostOperationEnabled, Observer,
95
		ICdmChangeListener, IContextListener,
96
		ICollapsableExpandable {
97

    
98
    private static final String RESTORING_TAXON_NAVIGATOR = Messages.TaxonNavigator_RESTORE;
99

    
100
	private static final String TREE_PATH = "treepath"; //$NON-NLS-1$
101

    
102
	private static final String TREE_PATHS = "treepaths"; //$NON-NLS-1$
103

    
104
	private final int dndOperations = DND.DROP_MOVE;
105

    
106
//	private ConversationHolder conversation;
107

    
108
	private IDataChangeBehavior dataChangeBehavior;
109

    
110
	private Root root;
111

    
112
	private TreeViewer viewer;
113

    
114
    @Inject
115
    private ESelectionService selService;
116

    
117
    @Inject
118
    private UISynchronize sync;
119

    
120
    private ISelectionChangedListener selectionChangedListener;
121

    
122
    private UndoContext undoContext;
123

    
124
    @Inject
125
    private MApplication application;
126

    
127
    @Inject
128
    private EModelService modelService;
129

    
130
    @Inject
131
    private EPartService partService;
132

    
133
    private boolean linkWithTaxon = false;
134

    
135
    @Inject
136
    public TaxonNavigatorE4() {
137
	    undoContext = new UndoContext();
138
	    CdmStore.getContextManager().addContextListener(this);
139
    }
140

    
141
	@PostConstruct
142
	private void create(Composite parent, EMenuService menuService, IEclipseContext context){
143
	    FillLayout layout = new FillLayout();
144
	    layout.marginHeight = 0;
145
	    layout.marginWidth = 0;
146
	    layout.type = SWT.VERTICAL;
147

    
148
	    parent.setLayout(layout);
149
	    viewer = new TreeViewer(new Tree(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI));
150
	    viewer.getControl().setLayoutData(LayoutConstants.FILL());
151

    
152
	    viewer.setContentProvider(new TaxonNavigatorContentProviderE4());
153
        viewer.setLabelProvider(new TaxonNavigatorLabelProviderE4());
154
        viewer.addDoubleClickListener(event->{
155
            ISelection selection = event.getSelection();
156
            if(selection instanceof IStructuredSelection){
157
                Object firstElement = ((IStructuredSelection) selection).getFirstElement();
158
                if(firstElement instanceof ICdmBase){
159
                    NavigationUtil.openEditor((ICdmBase) firstElement, viewer.getControl().getShell(), modelService, partService, application);
160
                }
161
                if(firstElement instanceof TaxonNodeDto){
162
                    NavigationUtil.openEditor((TaxonNodeDto) firstElement, viewer.getControl().getShell(), modelService, partService, application);
163
                }
164
            }
165
        });
166

    
167
        //propagate selection
168
        selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
169
        viewer.addSelectionChangedListener(selectionChangedListener);
170

    
171
        //create context menu
172
        menuService.registerContextMenu(viewer.getControl(), AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_NAVIGATOR_POPUPMENU_TAXONNAVIGATOR );
173

    
174
        //add drag'n'drop support
175
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer()};
176
        viewer.addDragSupport(dndOperations, transfers, new TreeNodeDragListenerE4(viewer));
177
        TreeNodeDropAdapterE4 dropAdapter = new TreeNodeDropAdapterE4(this);
178
        ContextInjectionFactory.inject(dropAdapter, context);
179
        viewer.addDropSupport(dndOperations, transfers, dropAdapter);
180

    
181
        updateSyncButton();
182

    
183
	    init();
184
	}
185

    
186
    protected void updateSyncButton() {
187
        MPart viewPart = partService.findPart(AppModelId.PARTDESCRIPTOR_EU_ETAXONOMY_TAXEDITOR_NAVIGATION_NAVIGATOR);
188
        if(viewPart!=null){
189
            MToolBar toolBar = viewPart.getToolbar();
190

    
191
            List<MToolBarElement> toolBarElements = toolBar.getChildren();
192

    
193
            MToolBarElement upperHandledMenuItem = toolBarElements.get(1);
194
            if (upperHandledMenuItem instanceof HandledToolItemImpl){
195
                ((HandledToolItemImpl)upperHandledMenuItem).setSelected(linkWithTaxon);
196
            }
197
        }
198
    }
199

    
200
	protected IAdaptable getInitialInput() {
201
		Comparator<TaxonNodeDto> comparator = PreferencesUtil.getNodeComparator();
202

    
203
		TaxonNodeNavigatorComparator viewerComparator = new TaxonNodeNavigatorComparator(comparator);
204
		viewer.setComparator(viewerComparator);
205
		viewer.setComparer(new IElementComparer() {
206

    
207
    	        @Override
208
                public int hashCode(Object element) {
209
    	            if (element instanceof TaxonNodeDto){
210
        	            TaxonNodeDto nodeDto = (TaxonNodeDto)element;
211

    
212
        	            String s = nodeDto.getUuid().toString();
213
        	            if (s != null) {
214
        	                return s.hashCode();
215
        	            }
216
        	            return element.hashCode();
217
    	            }else{
218
    	                return element.toString().hashCode();
219
    	            }
220
    	        }
221

    
222
                @Override
223
                public boolean equals(Object element1, Object element2) {
224
                    if (element1 instanceof TaxonNodeDto && element2 instanceof TaxonNodeDto){
225
                        TaxonNodeDto node1 = (TaxonNodeDto)element1;
226
                        TaxonNodeDto node2 = (TaxonNodeDto)element2;
227
                        return (node1.getUuid().equals(node2.getUuid()));
228
                    }else {
229
                        return element1.equals(element2);
230
                    }
231
                }
232
    		}
233
		);
234

    
235
		if (CdmStore.isActive()) {
236

    
237
			// TODO when closing and reopening the taxon navigator
238
			// we do not preserve state. Closing the view, in contrary to
239
			// closing the whole application
240
			// should be handled by the state manager too
241
		    root = new Root();
242

    
243
			return root;
244
		}
245
		return new EmptyRoot();
246
	}
247

    
248
	public void init() {
249
//		if (CdmStore.isActive() && conversation == null) {
250
//			conversation = CdmStore.createConversation();
251
//			conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
252
//		}
253
		if (CdmStore.isActive()) {
254
//		    cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
255
		    CdmApplicationState.getCurrentDataChangeService().register(this);
256
		    viewer.setInput(getInitialInput());
257
		}
258
		CdmStore.getLoginManager().addObserver(this);
259

    
260
	}
261

    
262
	//Link with taxon selection
263
	@Inject
264
	@Optional
265
	public void updateCurrentTaxon(@UIEventTopic(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR)ITaxonEditor editor){
266
	    if(linkWithTaxon && editor!=null){
267
	        viewer.refresh();
268
	        TaxonNodeDto taxonNode = null;
269
	        if(editor.getTaxon()!=null && editor.getTaxon().getTaxonNodes()!=null){
270
	            if (editor instanceof TaxonNameEditorE4){
271
	                taxonNode = new TaxonNodeDto( ((TaxonNameEditorE4)editor).getEditorInput().getTaxonNode());
272
	            }else{
273
	                if (editor.getTaxon().getTaxonNodes() != null && !editor.getTaxon().getTaxonNodes().isEmpty()){
274
	                    taxonNode = new TaxonNodeDto(editor.getTaxon().getTaxonNodes().iterator().next());
275
	                }
276
	            }
277
                if (taxonNode != null){
278
                    viewer.reveal(taxonNode);
279
                    viewer.setSelection(new StructuredSelection(taxonNode));
280
                }else{
281
                    //TODO: show message in status bar
282
                }
283
	        }
284
	    }
285
	}
286

    
287
	@Inject
288
    @Optional
289
    public void updateLinkWithTaxon(@UIEventTopic(WorkbenchEventConstants.UPDATE_LINK_WITH_TAXON) boolean isDummy){
290
	    this.linkWithTaxon = !linkWithTaxon;
291

    
292
        if(this.isLinkWithTaxon()){
293
            this.updateCurrentTaxon(EventUtility.getTaxonEditor());
294
        }
295
	}
296

    
297
    public void setLinkWithTaxon(boolean linkWithTaxon) {
298
        this.linkWithTaxon = linkWithTaxon;
299
    }
300

    
301
    public boolean isLinkWithTaxon() {
302
        return linkWithTaxon;
303
    }
304

    
305
	/**
306
	 * Refresh this navigators viewer
307
	 */
308
	public void refresh() {
309
		
310
		if(!viewer.getTree().isDisposed()){
311
		    if (CdmStore.isActive()){
312

    
313
		        viewer.setInput(getInitialInput());
314
		    }
315
		    viewer.refresh();
316
		}
317

    
318
		updateSyncButton();
319
	}
320

    
321
	/**
322
     * Refresh this navigators viewer
323
     */
324
    public void refresh(Set<?> objects) {
325
        for(Object obj : objects) {
326
            viewer.refresh(obj);
327
        }
328
        updateSyncButton();
329
    }
330

    
331
    /**
332
     * Refresh this navigators viewer
333
     */
334
    public void refresh(Object object) {
335
        viewer.refresh(object);
336
        updateSyncButton();
337
    }
338

    
339
	/**
340
	 * Removes all content
341
	 */
342
	public void clear() {
343
	    viewer.setInput(new EmptyRoot());
344
	}
345

    
346
	private void restore(IMemento memento, IProgressMonitor monitor) {
347
	    root = new Root();//conversation);
348
		if (memento == null) {
349
		    viewer.setInput(root);
350
			return;
351
		}
352
		int mementoWork = 0;
353
		Set<TreePath> treePaths = new HashSet<>();
354
		IMemento[] treePathMementos = null;
355

    
356
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
357

    
358
		if (treePathsMemento != null) {
359
			treePathMementos = treePathsMemento.getChildren(TREE_PATH);
360
			mementoWork = treePathMementos.length;
361
		}
362
		// begin the monitor with steps for all tree paths and steps for
363
		// creating
364
		// conversation s.o., refreshing the tree and setting the paths
365
		IProgressMonitor subProgressMonitor = AbstractUtility
366
				.getSubProgressMonitor(monitor, 1);
367

    
368
		subProgressMonitor.beginTask(RESTORING_TAXON_NAVIGATOR,
369
				1 + mementoWork + 5);
370
		subProgressMonitor.subTask(RESTORING_TAXON_NAVIGATOR);
371
		subProgressMonitor.worked(1);
372

    
373
		//conversation = CdmStore.createConversation();
374
		subProgressMonitor.worked(1);
375
		//conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
376
		subProgressMonitor.worked(1);
377
		viewer.setInput(root);
378
		subProgressMonitor.worked(1);
379
		viewer.refresh();
380
		subProgressMonitor.worked(1);
381

    
382
		if (treePathMementos != null && treePathMementos.length > 0) {
383
			for (IMemento treePathMemento : treePathMementos) {
384
				TreePath treePath = createTreePathFromString(treePathMemento
385
						.getID());
386
				if (!subProgressMonitor.isCanceled() && treePath != null) {
387
					treePaths.add(treePath);
388
					subProgressMonitor.worked(1);
389
				}
390
			}
391
		}
392
		if (treePaths.size() > 0) {
393
			TaxonNavigatorE4.this.viewer.setExpandedTreePaths(
394
					treePaths.toArray(new TreePath[0]));
395
			subProgressMonitor.worked(1);
396
		}
397
		subProgressMonitor.done();
398
	}
399

    
400
	private TreePath createTreePathFromString(String string) {
401

    
402
		List<CdmBase> pathList = new ArrayList<>();
403

    
404
		if (string.length() == 0) {
405
            return null;
406
        }
407

    
408
		for (String uuid : string.split(" ")) { //$NON-NLS-1$
409
			CdmBase cdmBaseObject = CdmStore.getService(
410
					ITaxonNodeService.class).find(
411
					UUID.fromString(uuid));
412
			if (cdmBaseObject == null) {
413
				// is this a tree uuid?
414
				cdmBaseObject = CdmStore.getService(
415
						IClassificationService.class).load(
416
						UUID.fromString(uuid));
417

    
418
				if (cdmBaseObject == null) {
419
                    return null;
420
                }
421
			}
422
			pathList.add(cdmBaseObject);
423
		}
424
		return new TreePath(pathList.toArray());
425
	}
426

    
427
	@Override
428
	public void collapse() {
429
	    viewer.collapseAll();
430
	}
431

    
432
	@Override
433
	public void expand() {
434
	    viewer.expandAll();
435
	}
436

    
437
	
438

    
439
	@PreDestroy
440
	public void dispose() {
441
		dataChangeBehavior = null;
442
//		if (conversation != null) {
443
//			conversation.unregisterForDataStoreChanges(this);
444
//			conversation.close();
445
//		}
446
		if(CdmApplicationState.getCurrentDataChangeService() != null) {
447
		    CdmApplicationState.getCurrentDataChangeService().unregister(this);
448
		}
449
	}
450

    
451
	@Focus
452
	public void setFocus() {
453

    
454
	}
455

    
456
    public UISynchronize getSync() {
457
        return sync;
458
    }
459

    
460
    public TreeViewer getViewer() {
461
        return viewer;
462
    }
463

    
464
    public UndoContext getUndoContext() {
465
        return undoContext;
466
    }
467

    
468
	@Override
469
	public boolean postOperation(Object objectAffectedByOperation) {
470
	    viewer.refresh();
471
		return true;
472
	}
473

    
474
	@Override
475
	public boolean onComplete() {
476
		return true;
477
	}
478

    
479
	@Override
480
	public void update(Observable o, Object arg) {
481
		if(o instanceof LoginManager){
482
			refresh();
483
		}
484
	}
485

    
486
//    @Override
487
//    public void update(CdmDataChangeMap changeEvents) {
488
//        if (dataChangeBehavior == null) {
489
//            dataChangeBehavior = new TaxonNavigatorDataChangeBehaviorE4(this);
490
//        }
491
//
492
//        DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
493
//        updateSyncButton();
494
//
495
//    }
496

    
497
    public List<TaxonNodeDto> getRootEntities() {
498
        if(root != null) {
499
            return root.getParentBeans();
500
        }
501
        return null;
502
    }
503

    
504
    @Override
505
    public void onChange(CdmChangeEvent event) {
506
        Object[] expandedElements = viewer.getExpandedElements();
507
        refresh();
508
        for(CdmBase cb : event.getChangedObjects()) {
509
        	if(cb instanceof TaxonNode) {
510
                TaxonNode tn = (TaxonNode)cb;
511
                if(tn.getTaxon() == null) {
512
                    viewer.refresh(tn.getClassification());
513
                } else {
514
                    viewer.refresh(cb);
515
                }
516
            } else if (cb instanceof Classification) {
517
                if ( event.getAction().equals(Action.Create)){
518
                    root.addRootNode((Classification)cb);
519
                } else if ( event.getAction().equals(Action.Delete)){
520
                    root.removeRootNode((Classification)cb);
521
                }
522
                viewer.refresh();
523
            }
524
        }
525
        viewer.setExpandedElements(expandedElements);
526
    }
527

    
528
    @Override
529
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
530
        // TODO Auto-generated method stub
531
    }
532

    
533
    @Override
534
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
535
    }
536

    
537
    @Override
538
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
539
        if(viewer!=null && viewer.getControl()!=null && !viewer.getControl().isDisposed()){
540
            init();
541
        }
542
    }
543

    
544
    @Override
545
    public void contextRefresh(IProgressMonitor monitor) {
546
//        viewer.refresh();
547
    }
548

    
549
    @Override
550
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
551
    }
552

    
553
    @Inject
554
    @Optional
555
    private void updateView(@UIEventTopic(WorkbenchEventConstants.REFRESH_NAVIGATOR)TaxonNodeDto dto){
556
        if(dto!= null){
557
            Object[] expandedElements = viewer.getExpandedElements();
558
            ISelection sel = viewer.getSelection();
559
            refresh(dto);
560
            viewer.setExpandedElements(expandedElements);
561
            if (sel != null && !sel.isEmpty()){
562
                viewer.reveal(dto);
563
                viewer.setSelection(sel);
564
            }
565
        }
566
    }
567

    
568
    @Inject
569
    @Optional
570
    private void updateView(@UIEventTopic(WorkbenchEventConstants.REFRESH_NAVIGATOR)boolean refresh){
571
        if(refresh){
572
            Object[] expandedElements = viewer.getExpandedElements();
573
            refresh();
574
            viewer.setExpandedElements(expandedElements);
575
        }
576
    }
577
}
(3-3/6)