Project

General

Profile

Download (13.7 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

    
10
package eu.etaxonomy.taxeditor.navigation.navigator.e4;
11

    
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.Comparator;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Observable;
20
import java.util.Observer;
21
import java.util.Set;
22
import java.util.UUID;
23

    
24
import javax.annotation.PostConstruct;
25
import javax.annotation.PreDestroy;
26
import javax.inject.Inject;
27

    
28
import org.eclipse.core.commands.operations.UndoContext;
29
import org.eclipse.core.runtime.IAdaptable;
30
import org.eclipse.core.runtime.IProgressMonitor;
31
import org.eclipse.e4.ui.di.Focus;
32
import org.eclipse.e4.ui.di.UISynchronize;
33
import org.eclipse.e4.ui.services.EMenuService;
34
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
35
import org.eclipse.jface.util.LocalSelectionTransfer;
36
import org.eclipse.jface.viewers.ISelection;
37
import org.eclipse.jface.viewers.ISelectionChangedListener;
38
import org.eclipse.jface.viewers.IStructuredSelection;
39
import org.eclipse.jface.viewers.TreePath;
40
import org.eclipse.jface.viewers.TreeViewer;
41
import org.eclipse.swt.SWT;
42
import org.eclipse.swt.dnd.DND;
43
import org.eclipse.swt.dnd.Transfer;
44
import org.eclipse.swt.layout.FillLayout;
45
import org.eclipse.swt.widgets.Composite;
46
import org.eclipse.ui.IMemento;
47

    
48
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
49
import eu.etaxonomy.cdm.api.application.CdmChangeEvent;
50
import eu.etaxonomy.cdm.api.application.ICdmChangeListener;
51
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
52
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
53
import eu.etaxonomy.cdm.api.service.IClassificationService;
54
import eu.etaxonomy.cdm.model.common.CdmBase;
55
import eu.etaxonomy.cdm.model.common.ICdmBase;
56
import eu.etaxonomy.cdm.model.common.ITreeNode;
57
import eu.etaxonomy.cdm.model.taxon.Classification;
58
import eu.etaxonomy.cdm.model.taxon.TaxonNaturalComparator;
59
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
60
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByNameComparator;
61
import eu.etaxonomy.cdm.model.taxon.TaxonNodeByRankAndNameComparator;
62
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
63
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
64
import eu.etaxonomy.taxeditor.model.IContextListener;
65
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
66
import eu.etaxonomy.taxeditor.navigation.NavigationUtil;
67
import eu.etaxonomy.taxeditor.navigation.l10n.Messages;
68
import eu.etaxonomy.taxeditor.navigation.navigator.EmptyRoot;
69
import eu.etaxonomy.taxeditor.navigation.navigator.Root;
70
import eu.etaxonomy.taxeditor.navigation.navigator.TaxonNodeNavigatorComparator;
71
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
72
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
73
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
74
import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
75
import eu.etaxonomy.taxeditor.store.CdmStore;
76
import eu.etaxonomy.taxeditor.store.LoginManager;
77
import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
78

    
79
/**
80
 *
81
 * @author pplitzner
82
 * @since Sep 7, 2017
83
 *
84
 */
85
public class TaxonNavigatorE4 implements
86
		IPostOperationEnabled, IConversationEnabled, Observer,
87
		ICdmEntitySessionEnabled, ICdmChangeListener, IContextListener {
88

    
89
    private static final String RESTORING_TAXON_NAVIGATOR = Messages.TaxonNavigator_RESTORE;
90

    
91
	private static final String TREE_PATH = "treepath"; //$NON-NLS-1$
92

    
93
	private static final String TREE_PATHS = "treepaths"; //$NON-NLS-1$
94

    
95
	private final int dndOperations = DND.DROP_MOVE;
96

    
97
	private ConversationHolder conversation;
98

    
99
	private ICdmEntitySession cdmEntitySession;
100

    
101
	private IDataChangeBehavior dataChangeBehavior;
102

    
103
	private Root root;
104

    
105
	private TreeViewer viewer;
106

    
107
    @Inject
108
    private ESelectionService selService;
109

    
110
    @Inject
111
    private UISynchronize sync;
112

    
113
    private ISelectionChangedListener selectionChangedListener;
114

    
115
    private UndoContext undoContext;
116

    
117
    @Inject
118
    public TaxonNavigatorE4() {
119
	    undoContext = new UndoContext();
120
	    CdmStore.getContextManager().addContextListener(this);
121
    }
122

    
123
	@PostConstruct
124
	private void create(Composite parent, EMenuService menuService){
125
	    FillLayout layout = new FillLayout();
126
	    layout.marginHeight = 0;
127
	    layout.marginWidth = 0;
128
	    layout.type = SWT.VERTICAL;
129

    
130
	    parent.setLayout(layout);
131
	    viewer = new TreeViewer(parent);
132
	    viewer.getControl().setLayoutData(LayoutConstants.FILL());
133

    
134
	    viewer.setContentProvider(new TaxonNavigatorContentProviderE4());
135
        viewer.setLabelProvider(new TaxonNavigatorLabelProviderE4());
136
        viewer.addDoubleClickListener(event->{
137
            ISelection selection = event.getSelection();
138
            if(selection instanceof IStructuredSelection){
139
                Object firstElement = ((IStructuredSelection) selection).getFirstElement();
140
                if(firstElement instanceof ICdmBase){
141
                    NavigationUtil.openEditor((ICdmBase) firstElement, viewer.getControl().getShell());
142
                }
143
            }
144
        });
145

    
146
        //propagate selection
147
        selectionChangedListener = (event -> selService.setSelection(event.getSelection()));
148
        viewer.addSelectionChangedListener(selectionChangedListener);
149

    
150
        //create context menu
151
        menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.navigator.popupmenu.taxonnavigator");
152

    
153
        //add drag'n'drop support
154
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer()};
155
        viewer.addDragSupport(dndOperations, transfers, new TreeNodeDragListenerE4(viewer));
156
        viewer.addDropSupport(dndOperations, transfers, new TreeNodeDropAdapterE4(this));
157

    
158
	    init();
159
	}
160

    
161
	/** {@inheritDoc} */
162
	protected IAdaptable getInitialInput() {
163
		Comparator<TaxonNode> comparator;
164
		if (PreferencesUtil.getSortNodesNaturally()){
165
			comparator = new TaxonNaturalComparator();
166
		} else if (PreferencesUtil.getSortNodesStrictlyAlphabetically()){
167
			comparator = new TaxonNodeByNameComparator();
168
		}else {
169
			comparator = new TaxonNodeByRankAndNameComparator();
170
		}
171
		TaxonNodeNavigatorComparator viewerComparator = new TaxonNodeNavigatorComparator(comparator);
172
		viewer.setComparator(viewerComparator);
173
		//FIXME E4 migrate linking with editor
174
//        setLinkingEnabled(true);
175

    
176
		if (CdmStore.isActive()) {
177

    
178
			// TODO when closing and reopening the taxon navigator
179
			// we do not preserve state. Closing the view, in contrary to
180
			// closing the whole application
181
			// should be handled by the state manager too
182
		    root = new Root(conversation);
183

    
184
			return root;
185
		}
186
		return new EmptyRoot();
187
	}
188

    
189
	public void init() {
190
		if (CdmStore.isActive() && conversation == null) {
191
			conversation = CdmStore.createConversation();
192
			conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
193
		}
194
		if (CdmStore.isActive()) {
195
		    cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
196
		    CdmApplicationState.getCurrentDataChangeService().register(this);
197
		}
198
		CdmStore.getLoginManager().addObserver(this);
199
        viewer.setInput(getInitialInput());
200
	}
201

    
202
	/**
203
	 * Refresh this navigators viewer
204
	 */
205
	public void refresh() {
206
		if(getConversationHolder() != null){
207
			getConversationHolder().bind();
208
			//FIXME : Need to make sure this is a stable fix (ticket 3822)
209
			if(!getConversationHolder().isCompleted()){
210
			    getConversationHolder().commit();
211
			}
212
		}
213
		if(!viewer.getTree().isDisposed()){
214
		    viewer.refresh();
215
		}
216
	}
217

    
218
	/**
219
     * Refresh this navigators viewer
220
     */
221
    public void refresh(Set<?> objects) {
222
        for(Object obj : objects) {
223
            viewer.refresh(obj);
224
        }
225
    }
226

    
227
	/**
228
	 * Removes all content
229
	 */
230
	public void clear() {
231
	    viewer.setInput(new EmptyRoot());
232
	}
233

    
234
	public void restore(IMemento memento, IProgressMonitor monitor) {
235
	    root = new Root(conversation);
236
		if (memento == null) {
237
		    viewer.setInput(root);
238
			return;
239
		}
240
		int mementoWork = 0;
241
		Set<TreePath> treePaths = new HashSet<TreePath>();
242
		IMemento[] treePathMementos = null;
243

    
244
		IMemento treePathsMemento = memento.getChild(TREE_PATHS);
245

    
246
		if (treePathsMemento != null) {
247
			treePathMementos = treePathsMemento.getChildren(TREE_PATH);
248
			mementoWork = treePathMementos.length;
249
		}
250
		// begin the monitor with steps for all tree paths and steps for
251
		// creating
252
		// conversation s.o., refreshing the tree and setting the paths
253
		IProgressMonitor subProgressMonitor = NavigationUtil
254
				.getSubProgressMonitor(monitor, 1);
255

    
256
		subProgressMonitor.beginTask(RESTORING_TAXON_NAVIGATOR,
257
				1 + mementoWork + 5);
258
		subProgressMonitor.subTask(RESTORING_TAXON_NAVIGATOR);
259
		subProgressMonitor.worked(1);
260

    
261
		conversation = CdmStore.createConversation();
262
		subProgressMonitor.worked(1);
263
		conversation.registerForDataStoreChanges(TaxonNavigatorE4.this);
264
		subProgressMonitor.worked(1);
265
		viewer.setInput(root);
266
		subProgressMonitor.worked(1);
267
		viewer.refresh();
268
		subProgressMonitor.worked(1);
269

    
270
		if (treePathMementos != null && treePathMementos.length > 0) {
271
			for (IMemento treePathMemento : treePathMementos) {
272
				TreePath treePath = createTreePathFromString(treePathMemento
273
						.getID());
274
				if (!subProgressMonitor.isCanceled() && treePath != null) {
275
					treePaths.add(treePath);
276
					subProgressMonitor.worked(1);
277
				}
278
			}
279
		}
280
		if (treePaths.size() > 0) {
281
			TaxonNavigatorE4.this.viewer.setExpandedTreePaths(
282
					treePaths.toArray(new TreePath[0]));
283
			subProgressMonitor.worked(1);
284
		}
285
		subProgressMonitor.done();
286
	}
287

    
288
	private TreePath createTreePathFromString(String string) {
289

    
290
		List<CdmBase> pathList = new ArrayList<CdmBase>();
291

    
292
		if (string.length() == 0) {
293
            return null;
294
        }
295

    
296
		for (String uuid : string.split(" ")) { //$NON-NLS-1$
297
			CdmBase cdmBaseObject = CdmStore.getService(
298
					IClassificationService.class).getTaxonNodeByUuid(
299
					UUID.fromString(uuid));
300
			if (cdmBaseObject == null) {
301
				// is this a tree uuid?
302
				cdmBaseObject = CdmStore.getService(
303
						IClassificationService.class).load(
304
						UUID.fromString(uuid));
305

    
306
				if (cdmBaseObject == null) {
307
                    return null;
308
                }
309
			}
310
			pathList.add(cdmBaseObject);
311
		}
312
		return new TreePath(pathList.toArray());
313
	}
314

    
315
	@Override
316
	public ConversationHolder getConversationHolder() {
317
		return conversation;
318
	}
319

    
320
	/** {@inheritDoc} */
321
	@PreDestroy
322
	public void dispose() {
323
		dataChangeBehavior = null;
324
		if (conversation != null) {
325
			conversation.unregisterForDataStoreChanges(this);
326
		}
327
		if(cdmEntitySession != null) {
328
		    cdmEntitySession.dispose();
329
		}
330
		if(CdmApplicationState.getCurrentDataChangeService() != null) {
331
		    CdmApplicationState.getCurrentDataChangeService().unregister(this);
332
		}
333
	}
334

    
335
	/** {@inheritDoc} */
336
	@Focus
337
	public void setFocus() {
338
		if (getConversationHolder() != null) {
339
			getConversationHolder().bind();
340
		}
341
		if(cdmEntitySession != null) {
342
		    cdmEntitySession.bind();
343
		}
344
	}
345

    
346
    public UISynchronize getSync() {
347
        return sync;
348
    }
349

    
350
    public TreeViewer getViewer() {
351
        return viewer;
352
    }
353

    
354
    public UndoContext getUndoContext() {
355
        return undoContext;
356
    }
357

    
358
	/** {@inheritDoc} */
359
	@Override
360
	public boolean postOperation(CdmBase objectAffectedByOperation) {
361
	    viewer.refresh();
362
		return true;
363
	}
364

    
365
	@Override
366
	public boolean onComplete() {
367
		return true;
368
	}
369

    
370
	@Override
371
	public void update(Observable o, Object arg) {
372
		if(o instanceof LoginManager){
373
			refresh();
374
		}
375
	}
376
	   /** {@inheritDoc} */
377
    @Override
378
    public void update(CdmDataChangeMap changeEvents) {
379
        if (dataChangeBehavior == null) {
380
            dataChangeBehavior = new TaxonNavigatorDataChangeBehaviorE4(this);
381
        }
382

    
383
        DataChangeBridge.handleDataChange(changeEvents, dataChangeBehavior);
384
    }
385

    
386
    @Override
387
    public ICdmEntitySession getCdmEntitySession() {
388
       return cdmEntitySession;
389
    }
390

    
391
    @Override
392
    public List<ITreeNode> getRootEntities() {
393
        if(root != null) {
394
            return root.getParentBeans();
395
        }
396
        return null;
397
    }
398

    
399
    @Override
400
    public void onChange(CdmChangeEvent event) {
401
        refresh();
402
        for(CdmBase cb : event.getChangedObjects()) {
403
        	if(cb instanceof TaxonNode) {
404
                TaxonNode tn = (TaxonNode)cb;
405
                if(tn.getTaxon() == null) {
406
                    viewer.refresh(tn.getClassification());
407
                } else {
408
                    viewer.refresh(cb);
409
                }
410
            } else if (cb instanceof Classification) {
411
                viewer.refresh();
412
            }
413
        }
414
    }
415

    
416
    @Override
417
    public Map<Object, List<String>> getPropertyPathsMap() {
418
        Map<Object, List<String>> propertyPathsMap = new HashMap<Object, List<String>>();
419
        List<String> taxonNodePropertyPaths = Arrays.asList(new String[] {
420
                "taxon.name" //$NON-NLS-1$
421
        });
422
         propertyPathsMap.put("childNodes", taxonNodePropertyPaths); //$NON-NLS-1$
423
        return propertyPathsMap;
424
    }
425

    
426
    /**
427
     * {@inheritDoc}
428
     */
429
    @Override
430
    public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
431
        // TODO Auto-generated method stub
432

    
433
    }
434

    
435
    /**
436
     * {@inheritDoc}
437
     */
438
    @Override
439
    public void contextStop(IMemento memento, IProgressMonitor monitor) {
440
    }
441

    
442
    /**
443
     * {@inheritDoc}
444
     */
445
    @Override
446
    public void contextStart(IMemento memento, IProgressMonitor monitor) {
447
        if(viewer!=null){
448
            init();
449
        }
450
    }
451

    
452
    /**
453
     * {@inheritDoc}
454
     */
455
    @Override
456
    public void contextRefresh(IProgressMonitor monitor) {
457
    }
458

    
459
    /**
460
     * {@inheritDoc}
461
     */
462
    @Override
463
    public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
464
    }
465
}
(3-3/6)