fef243c6baef4729bbc5419a1298ac0eeecdd3b4
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / featuretree / e4 / FeatureTreeEditor.java
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.Arrays;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17
18 import javax.annotation.PostConstruct;
19 import javax.annotation.PreDestroy;
20 import javax.inject.Inject;
21
22 import org.eclipse.core.runtime.IProgressMonitor;
23 import org.eclipse.e4.ui.di.Focus;
24 import org.eclipse.e4.ui.di.Persist;
25 import org.eclipse.e4.ui.di.UISynchronize;
26 import org.eclipse.e4.ui.model.application.ui.MDirtyable;
27 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
28 import org.eclipse.e4.ui.services.EMenuService;
29 import org.eclipse.e4.ui.workbench.modeling.EPartService;
30 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
31 import org.eclipse.jface.util.LocalSelectionTransfer;
32 import org.eclipse.jface.viewers.ISelection;
33 import org.eclipse.jface.viewers.ISelectionChangedListener;
34 import org.eclipse.jface.viewers.IStructuredSelection;
35 import org.eclipse.jface.viewers.SelectionChangedEvent;
36 import org.eclipse.jface.viewers.StructuredSelection;
37 import org.eclipse.jface.viewers.TreeViewer;
38 import org.eclipse.swt.SWT;
39 import org.eclipse.swt.dnd.DND;
40 import org.eclipse.swt.dnd.Transfer;
41 import org.eclipse.swt.events.KeyAdapter;
42 import org.eclipse.swt.events.KeyEvent;
43 import org.eclipse.swt.layout.FillLayout;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.ui.IMemento;
46
47 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
48 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
49 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
50 import eu.etaxonomy.cdm.model.term.FeatureNode;
51 import eu.etaxonomy.cdm.model.term.FeatureTree;
52 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
53 import eu.etaxonomy.taxeditor.editor.definedterm.TermTransfer;
54 import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
55 import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
56 import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
57 import eu.etaxonomy.taxeditor.featuretree.e4.operation.AddFeatureOperation;
58 import eu.etaxonomy.taxeditor.model.AbstractUtility;
59 import eu.etaxonomy.taxeditor.model.IContextListener;
60 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
61 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
62 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
63 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
64 import eu.etaxonomy.taxeditor.store.AppModelId;
65 import eu.etaxonomy.taxeditor.store.CdmStore;
66 import eu.etaxonomy.taxeditor.store.StoreUtil;
67 import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
68
69 /**
70 *
71 * @author pplitzner
72 * @date 06.06.2017
73 *
74 */
75 public class FeatureTreeEditor implements IFeatureTreeEditor, ISelectionChangedListener,
76 IE4ViewerPart, IPartContentHasDetails, IPartContentHasSupplementalData,
77 IContextListener, IConversationEnabled, IDirtyMarkable {
78
79 private ConversationHolder conversation;
80
81 private ICdmEntitySession cdmEntitySession;
82
83 @Inject
84 private ESelectionService selService;
85
86 @Inject
87 private MDirtyable dirty;
88
89 @Inject
90 private UISynchronize sync;
91
92 @Inject
93 private MPart thisPart;
94
95 private TreeViewer viewer;
96
97 @Inject
98 public FeatureTreeEditor() {
99 CdmStore.getContextManager().addContextListener(this);
100 }
101
102 @PostConstruct
103 public void createControl(Composite parent, EMenuService menuService){
104 if (CdmStore.isActive()){
105 initSession();
106 }
107 else{
108 return;
109 }
110 parent.setLayout(new FillLayout());
111 viewer = new TreeViewer(parent);
112 viewer.setContentProvider(new FeatureTreeContentProvider());
113 viewer.setLabelProvider(new FeatureTreeLabelProvider());
114
115 int ops = DND.DROP_COPY | DND.DROP_MOVE;
116 Transfer[] transfers = new Transfer[] {
117 FeatureNodeTransfer.getInstance(),
118 TermTransfer.getInstance(),
119 LocalSelectionTransfer.getTransfer()};
120 viewer.addDragSupport(ops, transfers, new FeatureNodeDragListener(viewer));
121 viewer.addDropSupport(ops, transfers, new FeatureTreeDropAdapter(this, viewer, sync));
122 viewer.addSelectionChangedListener(this);
123 viewer.getTree().addKeyListener(new KeyAdapter() {
124 @Override
125 public void keyPressed(KeyEvent e) {
126 if(e.stateMask == SWT.MOD1 && e.keyCode == 'c'){
127 copy(viewer.getStructuredSelection());
128 }
129 else if(e.stateMask == SWT.MOD1 && e.keyCode == 'v'){
130 paste(viewer.getStructuredSelection());
131 }
132 }
133 });
134
135 List<FeatureTree> trees = CdmStore.getService(IFeatureTreeService.class).list(FeatureTree.class, null, null, null, null);
136 Collections.sort(trees, (tree1, tree2) -> tree1.getTitleCache().compareTo(tree2.getTitleCache()));
137 viewer.setInput(trees);
138
139 //create context menu
140 menuService.registerContextMenu(viewer.getControl(), AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_STORE_POPUPMENU_FEATURETREEEDITOR);
141 }
142
143 public void paste(IStructuredSelection selection) {
144 if (StoreUtil.promptCheckIsDirty(this)) {
145 return;
146 }
147
148 ISelection clipBoardSelection = LocalSelectionTransfer.getTransfer().getSelection();
149 Object firstElement = selection.getFirstElement();
150 FeatureNode parentNode = null;
151 if(firstElement instanceof FeatureNode){
152 parentNode = (FeatureNode) firstElement;
153 }
154 else if(firstElement instanceof FeatureTree){
155 parentNode = ((FeatureTree)firstElement).getRoot();
156 }
157 if(parentNode!=null){
158 FeatureNode copiedNode = (FeatureNode) ((IStructuredSelection)clipBoardSelection).getFirstElement();
159
160 AddFeatureOperation operation = new AddFeatureOperation(copiedNode.getTerm().getUuid(), parentNode, this, this);
161 AbstractUtility.executeOperation(operation, sync);
162 }
163
164 }
165
166 public void copy(IStructuredSelection selection) {
167 LocalSelectionTransfer.getTransfer().setSelection(selection);
168 }
169
170 private void initSession(){
171 if(conversation == null){
172 conversation = CdmStore.createConversation();
173 }
174 if(cdmEntitySession==null){
175 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
176 }
177 }
178
179 private void clearSession() {
180 if(conversation!=null){
181 conversation.close();
182 conversation = null;
183 }
184 if(cdmEntitySession != null) {
185 cdmEntitySession.dispose();
186 cdmEntitySession = null;
187 }
188 dirty.setDirty(false);
189 }
190
191 public void setDirty(boolean isDirty){
192 this.dirty.setDirty(isDirty);
193 }
194
195 @Override
196 public boolean isDirty(){
197 return dirty.isDirty();
198 }
199
200 @Override
201 public void selectionChanged(SelectionChangedEvent event) {
202 //propagate selection
203 selService.setSelection(event.getSelection());
204 }
205
206 @Focus
207 public void focus(){
208 if(viewer!=null){
209 viewer.getControl().setFocus();
210 }
211 if(conversation!=null && !conversation.isBound()){
212 conversation.bind();
213 }
214 if(cdmEntitySession != null) {
215 cdmEntitySession.bind();
216 }
217 }
218
219 @Override
220 public void refresh(){
221 viewer.refresh();
222 }
223
224 public TreeViewer getViewer(){
225 return viewer;
226 }
227
228 @Override
229 public IStructuredSelection getSelection() {
230 return (IStructuredSelection) viewer.getSelection();
231 }
232
233 @Override
234 public ConversationHolder getConversationHolder() {
235 return conversation;
236 }
237
238 @Override
239 @Persist
240 public void save(IProgressMonitor monitor){
241 if (!conversation.isBound()) {
242 conversation.bind();
243 }
244
245 // commit the conversation and start a new transaction immediately
246 conversation.commit(true);
247
248 CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(getRootEntities());
249
250 initializeTrees();
251
252 this.setDirty(false);
253 }
254
255 private void initializeTrees() {
256 Object[] expandedElements = viewer.getExpandedElements();
257 viewer.getTree().removeAll();
258 List<FeatureTree> trees = CdmStore.getService(IFeatureTreeService.class).list(FeatureTree.class, null, null, null, null);
259 viewer.setInput(trees);
260 viewer.setExpandedElements(expandedElements);
261 }
262
263 @PreDestroy
264 public void dispose(){
265 selService.setSelection(null);
266 clearSession();
267 }
268
269 @Override
270 public ICdmEntitySession getCdmEntitySession() {
271 return cdmEntitySession;
272 }
273
274 @Override
275 public Map<Object, List<String>> getPropertyPathsMap() {
276 List<String> propertyPaths = Arrays.asList(new String[] {
277 "children", //$NON-NLS-1$
278 "feature", //$NON-NLS-1$
279 "featureTree", //$NON-NLS-1$
280 });
281 Map<Object, List<String>> propertyPathMap =
282 new HashMap<Object, List<String>>();
283 propertyPathMap.put(FeatureNode.class,propertyPaths);
284 return propertyPathMap;
285 }
286
287 @Override
288 public List<FeatureTree> getRootEntities() {
289 return (List<FeatureTree>) viewer.getInput();
290 }
291
292 @Override
293 public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
294 }
295
296 @Override
297 public void contextStop(IMemento memento, IProgressMonitor monitor) {
298 //close view when workbench closes
299 try{
300 thisPart.getContext().get(EPartService.class).hidePart(thisPart);
301 }
302 catch(Exception e){
303 //nothing
304 }
305 }
306
307 @Override
308 public void contextStart(IMemento memento, IProgressMonitor monitor) {
309 }
310
311 @Override
312 public void contextRefresh(IProgressMonitor monitor) {
313 }
314
315 @Override
316 public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
317 }
318
319 @Override
320 public void update(CdmDataChangeMap arg0) {
321 }
322
323 @Override
324 public void changed(Object element) {
325 dirty.setDirty(true);
326 viewer.refresh();
327 }
328
329 @Override
330 public void forceDirty() {
331 dirty.setDirty(true);
332 }
333
334 @Override
335 public boolean postOperation(Object objectAffectedByOperation) {
336 initializeTrees();
337 viewer.refresh();
338 if(objectAffectedByOperation instanceof FeatureNode){
339 FeatureNode node = (FeatureNode)objectAffectedByOperation;
340 viewer.expandToLevel(node.getFeatureTree(), 1);
341 }
342 if(objectAffectedByOperation!=null){
343 StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
344 viewer.setSelection(selection);
345 }
346 return true;
347 }
348
349 @Override
350 public boolean onComplete() {
351 return false;
352 }
353
354 }