Project

General

Profile

Download (12.4 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.Persist;
20
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
21
import org.eclipse.e4.ui.services.IServiceConstants;
22
import org.eclipse.jface.viewers.ISelectionChangedListener;
23
import org.eclipse.jface.viewers.IStructuredSelection;
24
import org.eclipse.jface.viewers.SelectionChangedEvent;
25
import org.eclipse.jface.viewers.TreeViewer;
26
import org.eclipse.jface.viewers.Viewer;
27
import org.eclipse.jface.viewers.ViewerDropAdapter;
28
import org.eclipse.jface.wizard.WizardDialog;
29
import org.eclipse.swt.SWT;
30
import org.eclipse.swt.dnd.DND;
31
import org.eclipse.swt.dnd.DragSourceAdapter;
32
import org.eclipse.swt.dnd.DragSourceEvent;
33
import org.eclipse.swt.dnd.Transfer;
34
import org.eclipse.swt.dnd.TransferData;
35
import org.eclipse.swt.events.ModifyEvent;
36
import org.eclipse.swt.events.ModifyListener;
37
import org.eclipse.swt.events.SelectionAdapter;
38
import org.eclipse.swt.events.SelectionEvent;
39
import org.eclipse.swt.events.SelectionListener;
40
import org.eclipse.swt.layout.GridData;
41
import org.eclipse.swt.layout.GridLayout;
42
import org.eclipse.swt.widgets.Button;
43
import org.eclipse.swt.widgets.Composite;
44
import org.eclipse.swt.widgets.Label;
45
import org.eclipse.swt.widgets.Shell;
46
import org.eclipse.swt.widgets.Text;
47
import org.eclipse.swt.widgets.Tree;
48

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

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

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

    
85
    private ConversationHolder conversation;
86
    @Inject
87
    private MDirtyable dirty;
88

    
89
    private Shell shell;
90

    
91
    @Inject
92
    public FeatureTreeEditor(@Named(IServiceConstants.ACTIVE_SHELL)Shell shell) {
93
        this.shell = shell;
94
        if(conversation==null){
95
            conversation = CdmStore.createConversation();
96
        }
97
    }
98

    
99
	/** {@inheritDoc} */
100
	@PostConstruct
101
	public void createControl(Composite parent, @Named(IServiceConstants.ACTIVE_SHELL)Shell shell) {
102
	    parent.setLayout(new GridLayout());
103
		Composite composite = new Composite(parent, SWT.NULL);
104
		composite.setLayout(new GridLayout());
105
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
106

    
107
		Composite composite_treeTitle = new Composite(composite, SWT.NULL);
108
		composite_treeTitle.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
109
				false));
110
		composite_treeTitle.setLayout(new GridLayout(4, false));
111

    
112
		label_title = new Label(composite_treeTitle, SWT.NULL);
113
		label_title.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
114
		label_title.setText("Title");
115

    
116
		text_title = new Text(composite_treeTitle, SWT.BORDER);
117
		text_title.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
118

    
119
		btnOpenFeatureTree = new Button(composite_treeTitle, SWT.NONE);
120
		btnOpenFeatureTree.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
121
		btnOpenFeatureTree.setText("Open Tree");
122

    
123
		btnNewFeatureTree = new Button(composite_treeTitle, SWT.NONE);
124
		btnNewFeatureTree.setText("New Feature Tree");
125

    
126
		Composite composite_treeContent = new Composite(composite, SWT.NULL);
127
		composite_treeContent.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
128
				true, true));
129
		composite_treeContent.setLayout(new GridLayout(2, false));
130

    
131
		viewer = new TreeViewer(composite_treeContent);
132
		Tree tree = viewer.getTree();
133
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
134
		viewer.getControl().setLayoutData(
135
				new GridData(SWT.FILL, SWT.FILL, true, true));
136

    
137
		Composite composite_buttons = new Composite(composite_treeContent,
138
				SWT.NULL);
139
		composite_buttons.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false,
140
				false));
141
		composite_buttons.setLayout(new GridLayout());
142

    
143
		button_add = new Button(composite_buttons, SWT.PUSH);
144
		button_add.setText("Add");
145
		button_add.setToolTipText("Add a feature to this feature treee.");
146
		button_remove = new Button(composite_buttons, SWT.PUSH);
147
		button_remove.setText("Remove");
148
		button_remove
149
				.setToolTipText("Remove a feature from this feature tree.");
150

    
151
		label_treeInfo = new Label(composite, SWT.NULL);
152
		label_treeInfo
153
				.setText("Order and nesting of feature nodes may be changed through drag and drop.");
154

    
155
		init(shell);
156
	}
157

    
158
	private void setDirty(boolean isDirty){
159
	    this.dirty.setDirty(isDirty);
160
	}
161

    
162
    private void init(Shell shell) {
163
        viewer.setContentProvider(new FeatureTreeContentProvider());
164
        viewer.setLabelProvider(new FeatureTreeLabelProvider());
165

    
166
        int ops = DND.DROP_COPY | DND.DROP_MOVE;
167
        Transfer[] transfers = new Transfer[] { FeatureNodeTransfer
168
                .getInstance() };
169
        viewer.addDragSupport(ops, transfers, new FeatureNodeDragListener(
170
                viewer));
171
        viewer.addDropSupport(ops, transfers,
172
                new FeatureNodeDropAdapter(viewer));
173

    
174
        viewer.addSelectionChangedListener(this);
175

    
176
        button_add.addSelectionListener(new AddButtonListener());
177
        button_remove.addSelectionListener(new RemoveSelectionListener());
178

    
179
        btnOpenFeatureTree.addSelectionListener(new SelectionListener() {
180

    
181
            @Override
182
            public void widgetSelected(SelectionEvent e) {
183
                FeatureTree tree = FeatureTreeSelectionDialog.select(shell, conversation, null);
184
                setSelectedTree(tree);
185
            }
186

    
187
            @Override
188
            public void widgetDefaultSelected(SelectionEvent e) {
189
            }
190
        });
191
    }
192

    
193
    public void setSelectedTree(FeatureTree featureTree) {
194
		this.featureTree = HibernateProxyHelper.deproxy(featureTree, FeatureTree.class);
195
		this.featureTree.setRoot(HibernateProxyHelper.deproxy(featureTree.getRoot(), FeatureNode.class));
196
		viewer.setInput(featureTree);
197

    
198
		text_title.removeModifyListener(this);
199
		text_title.setText(featureTree.getTitleCache());
200
		text_title.addModifyListener(this);
201
	}
202

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

    
210
	/** {@inheritDoc} */
211
	@Override
212
	public void selectionChanged(SelectionChangedEvent event) {
213
		IStructuredSelection selection = (IStructuredSelection) event
214
				.getSelection();
215

    
216
		button_add.setEnabled(selection.size() <= 1);
217
		button_remove.setEnabled(selection.size() > 0);
218
	}
219

    
220
	@Persist
221
	public void save(){
222
	    CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(featureTree);
223
	    setDirty(false);
224
	}
225

    
226
	private class AddButtonListener extends SelectionAdapter {
227
		@Override
228
		public void widgetSelected(SelectionEvent e) {
229
			AvailableFeaturesWizard wizard = new AvailableFeaturesWizard(
230
					featureTree);
231
			WizardDialog dialog = new WizardDialog(shell, wizard);
232

    
233
			if (dialog.open() == IStatus.OK) {
234
				IStructuredSelection selection = (IStructuredSelection) viewer
235
						.getSelection();
236
				FeatureNode parent = (FeatureNode) (selection.getFirstElement() != null ? selection
237
						.getFirstElement() : ((FeatureTree) viewer.getInput())
238
						.getRoot());
239
				Collection<Feature> additionalFeatures = wizard
240
						.getAdditionalFeatures();
241
				for (Feature feature : additionalFeatures) {
242
					FeatureNode child = FeatureNode.NewInstance(feature);
243
					CdmStore.getService(IFeatureNodeService.class).merge(child, true);
244

    
245
					parent.addChild(child);
246
				}
247
				setDirty(true);
248
				viewer.refresh();
249
			}
250
		}
251

    
252
	}
253

    
254
	private class RemoveSelectionListener extends SelectionAdapter {
255
		@Override
256
		public void widgetSelected(SelectionEvent e) {
257
			IStructuredSelection selection = (IStructuredSelection) viewer
258
					.getSelection();
259

    
260
			for (Object selectedObject : selection.toArray()) {
261
				FeatureNode featureNode = (FeatureNode) selectedObject;
262
				FeatureNode parent = featureNode.getParent();
263
				parent.removeChild(featureNode);
264

    
265
				CdmStore.getService(IFeatureNodeService.class).deleteFeatureNode(featureNode.getUuid(), new FeatureNodeDeletionConfigurator());
266

    
267
			}
268
			setDirty(true);
269
			viewer.refresh();
270
		}
271
	}
272

    
273
	private class FeatureNodeDragListener extends DragSourceAdapter {
274

    
275
		private final TreeViewer viewer;
276

    
277
		public FeatureNodeDragListener(TreeViewer viewer) {
278
			this.viewer = viewer;
279
		}
280

    
281
		/**
282
		 * Method declared on DragSourceListener
283
		 */
284
		@Override
285
		public void dragFinished(DragSourceEvent event) {
286
			if (!event.doit) {
287
                return;
288
            }
289
			// if the featureNode was moved, remove it from the source viewer
290
			if (event.detail == DND.DROP_MOVE) {
291
				IStructuredSelection selection = (IStructuredSelection) viewer
292
						.getSelection();
293
				viewer.refresh();
294
			}
295
		}
296

    
297
		/**
298
		 * Method declared on DragSourceListener
299
		 */
300
		@Override
301
		public void dragSetData(DragSourceEvent event) {
302
			IStructuredSelection selection = (IStructuredSelection) viewer
303
					.getSelection();
304
			FeatureNode[] featureNodes = (FeatureNode[]) selection.toList()
305
					.toArray(new FeatureNode[selection.size()]);
306
			if (FeatureNodeTransfer.getInstance().isSupportedType(
307
					event.dataType)) {
308
				event.data = featureNodes;
309
			}
310
		}
311

    
312
		/**
313
		 * Method declared on DragSourceListener
314
		 */
315
		@Override
316
		public void dragStart(DragSourceEvent event) {
317
			event.doit = !viewer.getSelection().isEmpty();
318
		}
319

    
320
	}
321

    
322
	private class FeatureNodeDropAdapter extends ViewerDropAdapter {
323

    
324
		protected FeatureNodeDropAdapter(Viewer viewer) {
325
			super(viewer);
326
		}
327

    
328
		@Override
329
		public boolean performDrop(Object data) {
330
			FeatureNode target = (FeatureNode) getCurrentTarget();
331
			int position = 0;
332

    
333
			if (target != null) {
334
				int location = getCurrentLocation();
335
				FeatureNode parent = target.getParent();
336
				if (location == LOCATION_BEFORE) {
337
					position = Math.max(0, parent.getIndex(target) - 1);
338
					target = parent;
339
				}
340

    
341
				if (location == LOCATION_AFTER) {
342
					position = parent.getIndex(target);
343
					target = parent;
344
				}
345
			}
346

    
347
			// set target to root node if there is no target specified
348
			if (target == null) {
349
				FeatureTree featureTree = (FeatureTree) getViewer().getInput();
350
				target = featureTree.getRoot();
351
			}
352

    
353
			Object[] droppedObjects = (Object[]) data;
354
			TreeViewer viewer = (TreeViewer) getViewer();
355

    
356
			// cannot drop a feature node onto itself
357
			for (Object droppedObject : droppedObjects) {
358
				if (droppedObject == null) {
359
					MessagingUtils.warningDialog(
360
									"Operation not supported yet",
361
									this,
362
									"We are currently unable to change the order of freshly created "
363
											+ "feature trees nodes. Please close and reopen the dialog to change the order of features.");
364
					return false;
365
				}
366
				if (droppedObject.equals(target)) {
367
					return false;
368
				}
369
			}
370
			for (Object droppedObject : droppedObjects) {
371
				FeatureNode droppedNode = (FeatureNode) droppedObject;
372
				target.addChild(droppedNode, position);
373
				viewer.add(target, droppedNode);
374
				viewer.reveal(droppedNode);
375
			}
376
			return true;
377
		}
378

    
379
		@Override
380
		public boolean validateDrop(Object target, int operation,
381
				TransferData transferData) {
382
			return FeatureNodeTransfer.getInstance().isSupportedType(
383
					transferData);
384
		}
385

    
386
	}
387
}
    (1-1/1)