Project

General

Profile

Download (12.8 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.featuretree.e4;
11

    
12
import java.util.Collection;
13

    
14
import javax.annotation.PostConstruct;
15
import javax.inject.Inject;
16
import javax.inject.Named;
17

    
18
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.e4.ui.di.Focus;
20
import org.eclipse.e4.ui.di.Persist;
21
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
22
import org.eclipse.e4.ui.services.IServiceConstants;
23
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
24
import org.eclipse.jface.viewers.ISelectionChangedListener;
25
import org.eclipse.jface.viewers.IStructuredSelection;
26
import org.eclipse.jface.viewers.SelectionChangedEvent;
27
import org.eclipse.jface.viewers.TreeViewer;
28
import org.eclipse.jface.viewers.Viewer;
29
import org.eclipse.jface.viewers.ViewerDropAdapter;
30
import org.eclipse.jface.wizard.WizardDialog;
31
import org.eclipse.swt.SWT;
32
import org.eclipse.swt.dnd.DND;
33
import org.eclipse.swt.dnd.DragSourceAdapter;
34
import org.eclipse.swt.dnd.DragSourceEvent;
35
import org.eclipse.swt.dnd.Transfer;
36
import org.eclipse.swt.dnd.TransferData;
37
import org.eclipse.swt.events.ModifyEvent;
38
import org.eclipse.swt.events.ModifyListener;
39
import org.eclipse.swt.events.SelectionAdapter;
40
import org.eclipse.swt.events.SelectionEvent;
41
import org.eclipse.swt.events.SelectionListener;
42
import org.eclipse.swt.layout.GridData;
43
import org.eclipse.swt.layout.GridLayout;
44
import org.eclipse.swt.widgets.Button;
45
import org.eclipse.swt.widgets.Composite;
46
import org.eclipse.swt.widgets.Label;
47
import org.eclipse.swt.widgets.Shell;
48
import org.eclipse.swt.widgets.Text;
49
import org.eclipse.swt.widgets.Tree;
50

    
51
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
52
import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
53
import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
54
import eu.etaxonomy.cdm.api.service.config.FeatureNodeDeletionConfigurator;
55
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
56
import eu.etaxonomy.cdm.model.description.Feature;
57
import eu.etaxonomy.cdm.model.description.FeatureNode;
58
import eu.etaxonomy.cdm.model.description.FeatureTree;
59
import eu.etaxonomy.taxeditor.featuretree.AvailableFeaturesWizard;
60
import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
61
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
62
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
63
import eu.etaxonomy.taxeditor.model.ImageResources;
64
import eu.etaxonomy.taxeditor.model.MessagingUtils;
65
import eu.etaxonomy.taxeditor.store.CdmStore;
66
import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
67

    
68
/**
69
 *
70
 * @author pplitzner
71
 * @date 06.06.2017
72
 *
73
 */
74
public class FeatureTreeEditor implements
75
		ModifyListener, ISelectionChangedListener {
76

    
77
	private TreeViewer viewer;
78
	private Label label_title;
79
	private Button button_add;
80
	private Button button_remove;
81
	private FeatureTree featureTree;
82
	private Text text_title;
83
    private Button btnOpenFeatureTree;
84

    
85
    private ConversationHolder conversation;
86

    
87
    @Inject
88
    private ESelectionService selService;
89

    
90
    @Inject
91
    private MDirtyable dirty;
92

    
93
    private Shell shell;
94

    
95
    @Inject
96
    public FeatureTreeEditor(@Named(IServiceConstants.ACTIVE_SHELL)Shell shell) {
97
        this.shell = shell;
98
        if(conversation==null){
99
            conversation = CdmStore.createConversation();
100
        }
101
    }
102

    
103
	/** {@inheritDoc} */
104
	@PostConstruct
105
	public void createControl(Composite parent, @Named(IServiceConstants.ACTIVE_SHELL)Shell shell) {
106
	    parent.setLayout(new GridLayout(2, false));
107

    
108
		Composite composite_treeTitle = new Composite(parent, SWT.NULL);
109
		composite_treeTitle.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
110
				false));
111
		GridLayout gl_composite_treeTitle = new GridLayout(2, false);
112
		gl_composite_treeTitle.marginWidth = 0;
113
		composite_treeTitle.setLayout(gl_composite_treeTitle);
114

    
115
		label_title = new Label(composite_treeTitle, SWT.NULL);
116
		label_title.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
117
		label_title.setText("Feature Tree");
118

    
119
		text_title = new Text(composite_treeTitle, SWT.BORDER);
120
		text_title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
121
		text_title.setEditable(false);
122

    
123
		btnOpenFeatureTree = new Button(parent, SWT.NONE);
124
		btnOpenFeatureTree.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
125
		btnOpenFeatureTree.setToolTipText("Open Tree");
126
		btnOpenFeatureTree.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
127

    
128
		viewer = new TreeViewer(parent);
129
		Tree tree = viewer.getTree();
130
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
131
		viewer.getControl().setLayoutData(
132
				new GridData(SWT.FILL, SWT.FILL, true, true));
133

    
134
		Composite composite_buttons = new Composite(parent,
135
				SWT.NULL);
136
		composite_buttons.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false,
137
				false));
138
		composite_buttons.setLayout(new GridLayout());
139

    
140
		button_add = new Button(composite_buttons, SWT.PUSH);
141
		button_add.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
142
		button_add.setToolTipText("Add a feature to this feature tree.");
143
		button_add.setImage(ImageResources.getImage(ImageResources.ADD_EDIT));
144
		button_remove = new Button(composite_buttons, SWT.PUSH);
145
		button_remove.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
146
		button_remove.setToolTipText("Remove a feature from this feature tree.");
147
		button_remove.setImage(ImageResources.getImage(ImageResources.TRASH_ICON));
148

    
149
		init(shell);
150
	}
151

    
152
	private void setDirty(boolean isDirty){
153
	    this.dirty.setDirty(isDirty);
154
	}
155

    
156
    private void init(Shell shell) {
157
        viewer.setContentProvider(new FeatureTreeContentProvider());
158
        viewer.setLabelProvider(new FeatureTreeLabelProvider());
159

    
160
        int ops = DND.DROP_COPY | DND.DROP_MOVE;
161
        Transfer[] transfers = new Transfer[] { FeatureNodeTransfer
162
                .getInstance() };
163
        viewer.addDragSupport(ops, transfers, new FeatureNodeDragListener(
164
                viewer));
165
        viewer.addDropSupport(ops, transfers,
166
                new FeatureNodeDropAdapter(viewer));
167

    
168
        viewer.addSelectionChangedListener(this);
169

    
170
        button_add.addSelectionListener(new AddButtonListener());
171
        button_remove.addSelectionListener(new RemoveSelectionListener());
172

    
173
        btnOpenFeatureTree.addSelectionListener(new SelectionListener() {
174

    
175
            @Override
176
            public void widgetSelected(SelectionEvent e) {
177
                FeatureTree tree = FeatureTreeSelectionDialog.select(shell, conversation, null);
178
                if(tree!=null){
179
                    setSelectedTree(tree);
180
                }
181
            }
182

    
183
            @Override
184
            public void widgetDefaultSelected(SelectionEvent e) {
185
            }
186
        });
187
    }
188

    
189
    public void setSelectedTree(FeatureTree featureTree) {
190
		this.featureTree = HibernateProxyHelper.deproxy(featureTree, FeatureTree.class);
191
		this.featureTree.setRoot(HibernateProxyHelper.deproxy(featureTree.getRoot(), FeatureNode.class));
192
		viewer.setInput(featureTree);
193

    
194
		text_title.removeModifyListener(this);
195
		text_title.setText(featureTree.getTitleCache());
196
		text_title.addModifyListener(this);
197
		text_title.setEditable(true);
198
	}
199

    
200
	/** {@inheritDoc} */
201
	@Override
202
	public void modifyText(ModifyEvent e) {
203
		featureTree.setTitleCache(text_title.getText(), true);
204
		setDirty(true);
205
	}
206

    
207
	/** {@inheritDoc} */
208
	@Override
209
	public void selectionChanged(SelectionChangedEvent event) {
210
		IStructuredSelection selection = (IStructuredSelection) event
211
				.getSelection();
212

    
213
		button_add.setEnabled(selection.size() <= 1);
214
		button_remove.setEnabled(selection.size() > 0);
215
		//propagate selection
216
		IStructuredSelection isel = (IStructuredSelection) event.getSelection();
217
		selService.setSelection((isel.size() == 1 ? isel.getFirstElement() : isel.toArray()));
218
	}
219

    
220
	@Focus
221
	public void focus(){
222
	    viewer.getControl().setFocus();
223
        if(conversation!=null && !conversation.isBound()){
224
            conversation.bind();
225
        }
226
	}
227

    
228
	@Persist
229
	public void save(){
230
	    CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(featureTree);
231
	    setDirty(false);
232
	}
233

    
234
	private class AddButtonListener extends SelectionAdapter {
235
		@Override
236
		public void widgetSelected(SelectionEvent e) {
237
			AvailableFeaturesWizard wizard = new AvailableFeaturesWizard(
238
					featureTree);
239
			WizardDialog dialog = new WizardDialog(shell, wizard);
240

    
241
			if (dialog.open() == IStatus.OK) {
242
				IStructuredSelection selection = (IStructuredSelection) viewer
243
						.getSelection();
244
				FeatureNode parent = (FeatureNode) (selection.getFirstElement() != null ? selection
245
						.getFirstElement() : ((FeatureTree) viewer.getInput())
246
						.getRoot());
247
				Collection<Feature> additionalFeatures = wizard
248
						.getAdditionalFeatures();
249
				for (Feature feature : additionalFeatures) {
250
					FeatureNode child = FeatureNode.NewInstance(feature);
251
					CdmStore.getService(IFeatureNodeService.class).merge(child, true);
252

    
253
					parent.addChild(child);
254
				}
255
				setDirty(true);
256
				viewer.refresh();
257
			}
258
		}
259

    
260
	}
261

    
262
	private class RemoveSelectionListener extends SelectionAdapter {
263
		@Override
264
		public void widgetSelected(SelectionEvent e) {
265
			IStructuredSelection selection = (IStructuredSelection) viewer
266
					.getSelection();
267

    
268
			for (Object selectedObject : selection.toArray()) {
269
				FeatureNode featureNode = (FeatureNode) selectedObject;
270
				FeatureNode parent = featureNode.getParent();
271
				parent.removeChild(featureNode);
272

    
273
				CdmStore.getService(IFeatureNodeService.class).deleteFeatureNode(featureNode.getUuid(), new FeatureNodeDeletionConfigurator());
274

    
275
			}
276
			setDirty(true);
277
			viewer.refresh();
278
		}
279
	}
280

    
281
	private class FeatureNodeDragListener extends DragSourceAdapter {
282

    
283
		private final TreeViewer viewer;
284

    
285
		public FeatureNodeDragListener(TreeViewer viewer) {
286
			this.viewer = viewer;
287
		}
288

    
289
		/**
290
		 * Method declared on DragSourceListener
291
		 */
292
		@Override
293
		public void dragFinished(DragSourceEvent event) {
294
			if (!event.doit) {
295
                return;
296
            }
297
			// if the featureNode was moved, remove it from the source viewer
298
			if (event.detail == DND.DROP_MOVE) {
299
				IStructuredSelection selection = (IStructuredSelection) viewer
300
						.getSelection();
301
				viewer.remove(selection);
302
				viewer.refresh();
303
			}
304
		}
305

    
306
		/**
307
		 * Method declared on DragSourceListener
308
		 */
309
		@Override
310
		public void dragSetData(DragSourceEvent event) {
311
			IStructuredSelection selection = (IStructuredSelection) viewer
312
					.getSelection();
313
			FeatureNode[] featureNodes = (FeatureNode[]) selection.toList()
314
					.toArray(new FeatureNode[selection.size()]);
315
			if (FeatureNodeTransfer.getInstance().isSupportedType(
316
					event.dataType)) {
317
				event.data = featureNodes;
318
			}
319
		}
320

    
321
		/**
322
		 * Method declared on DragSourceListener
323
		 */
324
		@Override
325
		public void dragStart(DragSourceEvent event) {
326
			event.doit = !viewer.getSelection().isEmpty();
327
		}
328

    
329
	}
330

    
331
	private class FeatureNodeDropAdapter extends ViewerDropAdapter {
332

    
333
		protected FeatureNodeDropAdapter(Viewer viewer) {
334
			super(viewer);
335
		}
336

    
337
		@Override
338
		public boolean performDrop(Object data) {
339
			FeatureNode target = (FeatureNode) getCurrentTarget();
340
			int position = 0;
341

    
342
			if (target != null) {
343
				int location = getCurrentLocation();
344
				FeatureNode parent = target.getParent();
345
				if (location == LOCATION_BEFORE) {
346
					position = Math.max(0, parent.getIndex(target) - 1);
347
					target = parent;
348
				}
349

    
350
				if (location == LOCATION_AFTER) {
351
					position = parent.getIndex(target);
352
					target = parent;
353
				}
354
			}
355

    
356
			// set target to root node if there is no target specified
357
			if (target == null) {
358
				FeatureTree featureTree = (FeatureTree) getViewer().getInput();
359
				target = featureTree.getRoot();
360
			}
361

    
362
			Object[] droppedObjects = (Object[]) data;
363
			TreeViewer viewer = (TreeViewer) getViewer();
364

    
365
			// cannot drop a feature node onto itself
366
			for (Object droppedObject : droppedObjects) {
367
				if (droppedObject == null) {
368
					MessagingUtils.warningDialog(
369
									"Operation not supported yet",
370
									this,
371
									"We are currently unable to change the order of freshly created "
372
											+ "feature trees nodes. Please close and reopen the dialog to change the order of features.");
373
					return false;
374
				}
375
				if (droppedObject.equals(target)) {
376
					return false;
377
				}
378
			}
379
			for (Object droppedObject : droppedObjects) {
380
				FeatureNode droppedNode = (FeatureNode) droppedObject;
381
				target.addChild(droppedNode, position);
382
				viewer.add(target, droppedNode);
383
				viewer.reveal(droppedNode);
384
			}
385
            setDirty(true);
386
			return true;
387
		}
388

    
389
		@Override
390
		public boolean validateDrop(Object target, int operation,
391
				TransferData transferData) {
392
			return FeatureNodeTransfer.getInstance().isSupportedType(
393
					transferData);
394
		}
395

    
396
	}
397
}
    (1-1/1)