Merge branch 'release/4.11.0'
[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.ArrayList;
13 import java.util.Arrays;
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.core.runtime.NullProgressMonitor;
24 import org.eclipse.e4.ui.di.Focus;
25 import org.eclipse.e4.ui.di.Persist;
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.viewers.ISelectionChangedListener;
32 import org.eclipse.jface.viewers.IStructuredSelection;
33 import org.eclipse.jface.viewers.SelectionChangedEvent;
34 import org.eclipse.jface.viewers.TreeViewer;
35 import org.eclipse.swt.SWT;
36 import org.eclipse.swt.events.ModifyEvent;
37 import org.eclipse.swt.events.ModifyListener;
38 import org.eclipse.swt.events.SelectionAdapter;
39 import org.eclipse.swt.events.SelectionEvent;
40 import org.eclipse.swt.widgets.Composite;
41 import org.eclipse.ui.IMemento;
42
43 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
44 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
45 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
46 import eu.etaxonomy.cdm.model.description.FeatureNode;
47 import eu.etaxonomy.cdm.model.description.FeatureTree;
48 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
49 import eu.etaxonomy.taxeditor.model.AbstractUtility;
50 import eu.etaxonomy.taxeditor.model.IContextListener;
51 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
52 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
53 import eu.etaxonomy.taxeditor.model.MessagingUtils;
54 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
55 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
56 import eu.etaxonomy.taxeditor.store.CdmStore;
57 import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
58 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
59 import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
60
61 /**
62 *
63 * @author pplitzner
64 * @date 06.06.2017
65 *
66 */
67 public class FeatureTreeEditor implements ICdmEntitySessionEnabled, ModifyListener, ISelectionChangedListener,
68 IE4ViewerPart, IE4SavablePart, IPartContentHasDetails, IPartContentHasSupplementalData, IContextListener, IConversationEnabled {
69
70 private ConversationHolder conversation;
71
72 private ICdmEntitySession cdmEntitySession;
73
74 @Inject
75 private ESelectionService selService;
76
77 @Inject
78 private MDirtyable dirty;
79
80 private FeatureTreeEditorComposite composite;
81
82 @Inject
83 private MPart thisPart;
84
85 @Inject
86 public FeatureTreeEditor() {
87 CdmStore.getContextManager().addContextListener(this);
88 }
89
90 /** {@inheritDoc} */
91 @PostConstruct
92 public void createControl(Composite parent, EMenuService menuService){
93 if (CdmStore.isActive()){
94 if(conversation == null){
95 conversation = CdmStore.createConversation();
96 }
97 if(cdmEntitySession!=null){
98 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
99 }
100 }
101 else{
102 return;
103 }
104 composite = new FeatureTreeEditorComposite(parent, SWT.NULL);
105 composite.init(new FeatureNodeDragListener(composite.getViewer()),
106 new FeatureNodeDropAdapter(dirty, composite.getViewer()), this, new SelectionAdapter() {
107 @Override
108 public void widgetSelected(SelectionEvent e) {
109 if(isDirty()){
110 if(MessagingUtils.confirmDialog("Editor has to be saved", "You have to save before loading another feature tree. Save now?")){
111 save(new NullProgressMonitor());
112 }
113 else{
114 return;
115 }
116
117 }
118 FeatureTree tree = FeatureTreeSelectionDialog.select(composite.getDisplay().getActiveShell(), conversation, null);
119 if (tree != null) {
120 composite.setSelectedTree(tree, FeatureTreeEditor.this);
121 }
122 }
123 });
124
125 //create context menu
126 menuService.registerContextMenu(composite.getViewer().getControl(), "eu.etaxonomy.taxeditor.store.popupmenu.featureTreeEditor");
127 }
128
129 public void setDirty(boolean isDirty){
130 this.dirty.setDirty(isDirty);
131 }
132
133 public boolean isDirty(){
134 return dirty.isDirty();
135 }
136
137 public FeatureTree getSelectedFeatureTree(){
138 return composite.getFeatureTree();
139 }
140
141 /** {@inheritDoc} */
142 @Override
143 public void modifyText(ModifyEvent e) {
144 composite.getFeatureTree().setTitleCache(composite.getText_title().getText(), true);
145 setDirty(true);
146 }
147
148 /** {@inheritDoc} */
149 @Override
150 public void selectionChanged(SelectionChangedEvent event) {
151 //propagate selection
152 selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event));
153 }
154
155 @Focus
156 public void focus(){
157 if(composite!=null){
158 composite.getViewer().getControl().setFocus();
159 }
160 if(conversation!=null && !conversation.isBound()){
161 conversation.bind();
162 }
163 if(cdmEntitySession != null) {
164 cdmEntitySession.bind();
165 }
166 }
167
168 @Override
169 public void refresh(){
170 composite.getViewer().refresh();
171 }
172
173 public TreeViewer getViewer(){
174 return composite.getViewer();
175 }
176
177 /**
178 * {@inheritDoc}
179 */
180 @Override
181 public IStructuredSelection getSelection() {
182 return (IStructuredSelection) composite.getViewer().getSelection();
183 }
184
185 /**
186 * {@inheritDoc}
187 */
188 @Override
189 public ConversationHolder getConversationHolder() {
190 return conversation;
191 }
192
193 @Override
194 @Persist
195 public void save(IProgressMonitor monitor){
196 if (!conversation.isBound()) {
197 conversation.bind();
198 }
199
200 // commit the conversation and start a new transaction immediately
201 conversation.commit(true);
202
203 CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(composite.getFeatureTree());
204
205 this.setDirty(false);
206 }
207
208 @PreDestroy
209 public void dispose(){
210 if(conversation!=null){
211 conversation.close();
212 }
213 if(cdmEntitySession != null) {
214 cdmEntitySession.dispose();
215 }
216 }
217
218 @Override
219 public ICdmEntitySession getCdmEntitySession() {
220 return cdmEntitySession;
221 }
222
223 @Override
224 public Map<Object, List<String>> getPropertyPathsMap() {
225 List<String> propertyPaths = Arrays.asList(new String[] {
226 "children", //$NON-NLS-1$
227 "feature", //$NON-NLS-1$
228 "featureTree", //$NON-NLS-1$
229 });
230 Map<Object, List<String>> propertyPathMap =
231 new HashMap<Object, List<String>>();
232 propertyPathMap.put(FeatureNode.class,propertyPaths);
233 return propertyPathMap;
234 }
235
236 /**
237 * {@inheritDoc}
238 */
239 @Override
240 public List<FeatureTree> getRootEntities() {
241 List<FeatureTree> root = new ArrayList<>();
242 root.add(composite.getFeatureTree());
243 return root;
244 }
245
246 /**
247 * {@inheritDoc}
248 */
249 @Override
250 public void contextAboutToStop(IMemento memento, IProgressMonitor monitor) {
251 }
252
253 /**
254 * {@inheritDoc}
255 */
256 @Override
257 public void contextStop(IMemento memento, IProgressMonitor monitor) {
258 //close view when workbench closes
259 try{
260 thisPart.getContext().get(EPartService.class).hidePart(thisPart);
261 }
262 catch(Exception e){
263 //nothing
264 }
265 }
266
267 /**
268 * {@inheritDoc}
269 */
270 @Override
271 public void contextStart(IMemento memento, IProgressMonitor monitor) {
272 }
273
274 /**
275 * {@inheritDoc}
276 */
277 @Override
278 public void contextRefresh(IProgressMonitor monitor) {
279 }
280
281 /**
282 * {@inheritDoc}
283 */
284 @Override
285 public void workbenchShutdown(IMemento memento, IProgressMonitor monitor) {
286 }
287
288 /**
289 * {@inheritDoc}
290 */
291 @Override
292 public void update(CdmDataChangeMap arg0) {
293 }
294
295 }