ref #7086 Add "browse" and "delete" button to area selection in WSeditor
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / workingSet / WorkingSetEditor.java
1 /**
2 * Copyright (C) 2017 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 package eu.etaxonomy.taxeditor.editor.workingSet;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.UUID;
19
20 import javax.annotation.PostConstruct;
21 import javax.annotation.PreDestroy;
22 import javax.inject.Inject;
23 import javax.inject.Named;
24
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.e4.core.contexts.ContextInjectionFactory;
27 import org.eclipse.e4.core.contexts.IEclipseContext;
28 import org.eclipse.e4.ui.di.Focus;
29 import org.eclipse.e4.ui.di.Persist;
30 import org.eclipse.e4.ui.model.application.ui.MDirtyable;
31 import org.eclipse.e4.ui.services.IServiceConstants;
32 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
33 import org.eclipse.jface.util.LocalSelectionTransfer;
34 import org.eclipse.jface.viewers.IStructuredSelection;
35 import org.eclipse.jface.viewers.Viewer;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.dnd.DND;
38 import org.eclipse.swt.dnd.Transfer;
39 import org.eclipse.swt.events.KeyAdapter;
40 import org.eclipse.swt.events.KeyEvent;
41 import org.eclipse.swt.events.ModifyEvent;
42 import org.eclipse.swt.events.ModifyListener;
43 import org.eclipse.swt.events.SelectionAdapter;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Display;
46 import org.eclipse.swt.widgets.Shell;
47
48 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
49 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
50 import eu.etaxonomy.cdm.api.service.ITermService;
51 import eu.etaxonomy.cdm.api.service.IWorkingSetService;
52 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
53 import eu.etaxonomy.cdm.model.description.FeatureTree;
54 import eu.etaxonomy.cdm.model.description.WorkingSet;
55 import eu.etaxonomy.cdm.model.location.NamedArea;
56 import eu.etaxonomy.cdm.model.name.Rank;
57 import eu.etaxonomy.cdm.model.taxon.ITaxonTreeNode;
58 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
59 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
60 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
61 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
62 import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
63 import eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled;
64 import eu.etaxonomy.taxeditor.store.CdmStore;
65 import eu.etaxonomy.taxeditor.ui.dialog.selection.NamedAreaSelectionDialog;
66 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
67 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
68
69 /**
70 * @author pplitzner
71 * @since Nov 21, 2017
72 *
73 */
74 public class WorkingSetEditor implements IE4SavablePart, IConversationEnabled, ICdmEntitySessionEnabled,
75 IPartContentHasDetails, IDirtyMarkable {
76
77 private WorkingSetComposite composite;
78
79 private ConversationHolder conversation;
80
81 private ICdmEntitySession cdmEntitySession;
82
83 private WorkingSet workingSet;
84
85 private final int dndOperations = DND.DROP_MOVE;
86
87 @Inject
88 private MDirtyable dirty;
89
90 @Inject
91 private ESelectionService selectionService;
92
93 private ModifyListener labelModifyListener;
94
95 @PostConstruct
96 public void create(Composite parent, IEclipseContext context, @Named(IServiceConstants.ACTIVE_SHELL)Shell shell){
97 if (CdmStore.isActive()){
98 if(conversation == null){
99 conversation = CdmStore.createConversation();
100 }
101 if(cdmEntitySession == null){
102 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
103 }
104 }
105 else{
106 return;
107 }
108 CdmFormFactory cdmFormFactory = new CdmFormFactory(Display.getCurrent());
109 ContextInjectionFactory.inject(cdmFormFactory, context);
110
111 composite = new WorkingSetComposite(parent, SWT.NONE);
112
113 labelModifyListener = new ModifyListener() {
114 @Override
115 public void modifyText(ModifyEvent e) {
116 workingSet.setLabel(composite.getTxt_label().getText());
117 dirty.setDirty(true);
118 }
119 };
120 composite.getRankMin().addSelectionChangedListener(event->dirty.setDirty(true));
121 composite.getRankMax().addSelectionChangedListener(event->dirty.setDirty(true));
122
123 composite.getBtnChooseArea().addSelectionListener(new SelectionAdapter() {
124
125 @Override
126 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
127 NamedArea area = NamedAreaSelectionDialog.select(shell, null, null);
128 if(area!=null){
129 composite.setArea(area);
130 }
131 dirty.setDirty(true);
132 }
133 });
134 composite.getBtnRemoveArea().addSelectionListener(new SelectionAdapter() {
135
136 @Override
137 public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
138 composite.removeArea();
139 dirty.setDirty(true);
140 }
141 });
142
143 composite.getFeatureTreeEditorComposite().init(null, null, e->selectionService.setSelection(e.getSelection()), null);
144
145 //add drag'n'drop support
146 Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer()};
147 composite.getTaxonNodeTree().addDropSupport(dndOperations, transfers, new TaxonNodeDropAdapter(this));
148
149 composite.getTaxonNodeTree().getTree().addKeyListener(new KeyAdapter() {
150 @Override
151 public void keyPressed(KeyEvent e) {
152 if(e.character==SWT.DEL){
153 IStructuredSelection selection = (IStructuredSelection) composite.getTaxonNodeTree().getSelection();
154 Iterator<TaxonNode> iterator = selection.iterator();
155 while(iterator.hasNext()){
156 TaxonNode taxonNode = iterator.next();
157 removeTaxonNode(taxonNode);
158 }
159 }
160 }
161 });
162
163 }
164
165 public void init(UUID workingSetUuid) {
166 this.workingSet = CdmStore.getService(IWorkingSetService.class).load(workingSetUuid);
167 if(workingSet.getLabel()!=null){
168 composite.getTxt_label().setText(workingSet.getLabel());
169 }
170 if(workingSet.getDescriptiveSystem()!=null){
171 composite.setCharacters(workingSet.getDescriptiveSystem());
172 }
173 Rank maxRank = workingSet.getMaxRank();
174 if(maxRank!=null){
175 composite.setRankMax(maxRank);
176 }
177 Rank minRank = workingSet.getMinRank();
178 if(minRank!=null){
179 composite.setRankMin(minRank);
180 }
181 Set<NamedArea> geoFilter = workingSet.getGeoFilter();
182 if(geoFilter!=null && !geoFilter.isEmpty()){
183 composite.setArea(geoFilter.iterator().next());
184 }
185 Set<TaxonNode> taxonSubtreeFilter = workingSet.getTaxonSubtreeFilter();
186 if(taxonSubtreeFilter!=null){
187 composite.getTaxonNodeTree().setInput(taxonSubtreeFilter);
188 }
189
190 composite.getTxt_label().addModifyListener(labelModifyListener);
191 }
192
193 public void addTaxonNode(TaxonNode taxonNode){
194 //load into WS editor session
195 taxonNode = getCdmEntitySession().load(taxonNode, false);
196 Viewer taxonTreeViewer = getTaxonTreeViewer();
197 Object input = taxonTreeViewer.getInput();
198 Collection<TaxonNode> treeNodes;
199 if(input==null){
200 treeNodes = new ArrayList<>();
201 }
202 else{
203 treeNodes = (Collection<TaxonNode>) input;
204 }
205 treeNodes.add(taxonNode);
206 taxonTreeViewer.setInput(treeNodes);
207 dirty.setDirty(true);
208 }
209
210 private void removeTaxonNode(TaxonNode taxonNode){
211 Viewer taxonTreeViewer = getTaxonTreeViewer();
212 Collection<TaxonNode> input = (Collection<TaxonNode>) taxonTreeViewer.getInput();
213 input.remove(taxonNode);
214 taxonTreeViewer.setInput(input);
215 dirty.setDirty(true);
216 }
217
218 /**
219 * {@inheritDoc}
220 */
221 @Persist
222 @Override
223 public void save(IProgressMonitor monitor) {
224 NamedArea area = composite.getArea();
225 Set<NamedArea> areas = new HashSet<>();
226 if(area!=null){
227 areas.add(area);
228 }
229 Object input = composite.getTaxonNodeTree().getInput();
230 if(input!=null){
231 workingSet.setTaxonSubtreeFilter(new HashSet<>());//clear existing filter
232 Collection<ITaxonTreeNode> taxonNodes = (Collection<ITaxonTreeNode>) input;
233 for (ITaxonTreeNode taxonTreeNode : taxonNodes) {
234 if(taxonTreeNode instanceof TaxonNode){
235 TaxonNode taxonNode = (TaxonNode)taxonTreeNode;
236 workingSet.addTaxonSubtree(taxonNode);
237 }
238 }
239 }
240 FeatureTree characters = composite.getCharacters();
241 if(characters!=null){
242 //save characters because they can be modified in this editor
243 characters.getDistinctFeatures().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
244 }
245
246
247 DefinedTermBase rankMaxSelection = composite.getRankMax().getSelection();
248 Rank rankMax = null;
249 if(rankMaxSelection instanceof Rank){
250 rankMax = (Rank) rankMaxSelection;
251 }
252 DefinedTermBase rankMinSelection = composite.getRankMin().getSelection();
253 Rank rankMin = null;
254 if(rankMinSelection instanceof Rank){
255 rankMin = (Rank) rankMinSelection;
256 }
257
258 workingSet.setMaxRank(rankMax);
259 workingSet.setMinRank(rankMin);
260 workingSet.setDescriptiveSystem(characters);
261 workingSet.setGeoFilter(areas);
262
263 conversation.commit();
264 CdmStore.getService(IWorkingSetService.class).merge(workingSet, true);
265
266 dirty.setDirty(false);
267 }
268
269 /** {@inheritDoc} */
270 @PreDestroy
271 public void dispose() {
272 if (conversation != null) {
273 conversation.close();
274 conversation = null;
275 }
276 if(cdmEntitySession != null) {
277 cdmEntitySession.dispose();
278 cdmEntitySession = null;
279 }
280 dirty.setDirty(false);
281 }
282
283 /** {@inheritDoc} */
284 @Focus
285 public void setFocus() {
286 if (getConversationHolder() != null) {
287 getConversationHolder().bind();
288 }
289 if(cdmEntitySession != null) {
290 cdmEntitySession.bind();
291 }
292 }
293
294 public Viewer getTaxonTreeViewer() {
295 return composite.getTaxonNodeTree();
296 }
297
298 /**
299 * {@inheritDoc}
300 */
301 @Override
302 public void update(CdmDataChangeMap arg0) {
303 }
304
305 /**
306 * {@inheritDoc}
307 */
308 @Override
309 public ICdmEntitySession getCdmEntitySession() {
310 return cdmEntitySession;
311 }
312
313 /**
314 * {@inheritDoc}
315 */
316 @Override
317 public Collection<WorkingSet> getRootEntities() {
318 return null;
319 }
320
321 /**
322 * {@inheritDoc}
323 */
324 @Override
325 public Map<Object, List<String>> getPropertyPathsMap() {
326 return null;
327 }
328
329 /**
330 * {@inheritDoc}
331 */
332 @Override
333 public ConversationHolder getConversationHolder() {
334 return conversation;
335 }
336
337 /**
338 * {@inheritDoc}
339 */
340 @Override
341 public void changed(Object element) {
342 dirty.setDirty(true);
343 }
344
345 /**
346 * {@inheritDoc}
347 */
348 @Override
349 public void forceDirty() {
350 dirty.setDirty(true);
351 }
352
353 }