Merge branch 'release/4.11.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / workingSet / CharacterEditor.java
1 // $Id$
2 /**
3 * Copyright (C) 2017 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.taxeditor.editor.workingSet;
11
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18
19 import javax.annotation.PostConstruct;
20 import javax.annotation.PreDestroy;
21 import javax.inject.Inject;
22
23 import org.eclipse.core.runtime.IProgressMonitor;
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.services.EMenuService;
28 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
29 import org.eclipse.jface.viewers.ISelection;
30 import org.eclipse.jface.viewers.ISelectionChangedListener;
31 import org.eclipse.jface.viewers.IStructuredSelection;
32 import org.eclipse.jface.viewers.SelectionChangedEvent;
33 import org.eclipse.jface.viewers.TreeSelection;
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.custom.SashForm;
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.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.Display;
45 import org.eclipse.ui.forms.widgets.FormToolkit;
46
47 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
48 import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
49 import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
50 import eu.etaxonomy.cdm.api.service.ITermService;
51 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
52 import eu.etaxonomy.cdm.model.description.Character;
53 import eu.etaxonomy.cdm.model.description.FeatureNode;
54 import eu.etaxonomy.cdm.model.description.FeatureTree;
55 import eu.etaxonomy.taxeditor.featuretree.e4.FeatureNodeDragListener;
56 import eu.etaxonomy.taxeditor.featuretree.e4.FeatureNodeDropAdapter;
57 import eu.etaxonomy.taxeditor.featuretree.e4.FeatureTreeEditorComposite;
58 import eu.etaxonomy.taxeditor.model.AbstractUtility;
59 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
60 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
61 import eu.etaxonomy.taxeditor.model.MessagingUtils;
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.FeatureTreeSelectionDialog;
66 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
67 import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
68
69 /**
70 * @author pplitzner
71 * @date 24.05.2017
72 *
73 */
74 public class CharacterEditor
75 implements ICdmEntitySessionEnabled, ISelectionChangedListener, ModifyListener, IE4ViewerPart
76 , IPartContentHasDetails, IPartContentHasSupplementalData, IE4SavablePart{
77
78 private FeatureTreeEditorComposite characterTreeEditorComposite;
79 private FeatureTreeEditorComposite propertiesTreeEditorComposite;
80 private FeatureTreeEditorComposite structuresTreeEditorComposite;
81 private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
82 private Button btnAddCharacter;
83
84 @Inject
85 private ESelectionService selService;
86
87 @Inject
88 private MDirtyable dirty;
89
90 private ConversationHolder conversation;
91
92 private ICdmEntitySession cdmEntitySession;
93 private Composite composite;
94
95 public CharacterEditor() {
96 }
97
98 /**
99 * Create contents of the view part.
100 */
101 @PostConstruct
102 public void createControls(Composite parent, EMenuService menuService ) {
103 if (CdmStore.isActive()){
104 if(conversation == null){
105 conversation = CdmStore.createConversation();
106 }
107 if(cdmEntitySession!=null){
108 cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
109 }
110 }
111 else{
112 return;
113 }
114 parent.setLayout(new GridLayout(1, false));
115
116 SashForm sashForm = new SashForm(parent, SWT.NONE);
117 sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
118 formToolkit.adapt(sashForm);
119 formToolkit.paintBordersFor(sashForm);
120
121 composite = new Composite(sashForm, SWT.NONE);
122 formToolkit.adapt(composite);
123 formToolkit.paintBordersFor(composite);
124 GridLayout gl_composite = new GridLayout(1, false);
125 gl_composite.marginWidth = 0;
126 composite.setLayout(gl_composite);
127
128 structuresTreeEditorComposite = addFeatureTreeEditor(composite);
129 initFeatureTreeComposite(structuresTreeEditorComposite, null, null);
130 structuresTreeEditorComposite.getLabel_title().setText("Structures");
131
132 Composite composite_1 = new Composite(sashForm, SWT.NONE);
133 formToolkit.adapt(composite_1);
134 formToolkit.paintBordersFor(composite_1);
135 GridLayout gl_composite_1 = new GridLayout(1, false);
136 gl_composite_1.marginWidth = 0;
137 composite_1.setLayout(gl_composite_1);
138
139 propertiesTreeEditorComposite = addFeatureTreeEditor(composite_1);
140 initFeatureTreeComposite(propertiesTreeEditorComposite, null, null);
141 propertiesTreeEditorComposite.getLabel_title().setText("Properties");
142 //TODO: fix drag and drop
143 // initFeatureTreeComposite(treeViewerProperties, new CharacterDragListener(treeViewerStructures.getViewer(), treeViewerProperties.getViewer()), null);
144
145 Composite composite_3 = new Composite(sashForm, SWT.NONE);
146 formToolkit.adapt(composite_3);
147 formToolkit.paintBordersFor(composite_3);
148 GridLayout gl_composite_3 = new GridLayout(2, false);
149 gl_composite_3.marginWidth = 0;
150 composite_3.setLayout(gl_composite_3);
151
152 btnAddCharacter = new Button(composite_3, SWT.NONE);
153 btnAddCharacter.setText(">>");
154 formToolkit.adapt(btnAddCharacter, true, true);
155
156 characterTreeEditorComposite = addFeatureTreeEditor(composite_3);
157 initFeatureTreeComposite(characterTreeEditorComposite, new FeatureNodeDragListener(characterTreeEditorComposite.getViewer()), new FeatureNodeDropAdapter(dirty, characterTreeEditorComposite.getViewer()));
158 characterTreeEditorComposite.getLabel_title().setText("Characters");
159
160 //add context menu to character viewer//create context menu
161 menuService.registerContextMenu(characterTreeEditorComposite.getViewer().getControl(), "eu.etaxonomy.taxeditor.editor.popupmenu.characterEditor");
162
163 init();
164 }
165
166 private FeatureTreeEditorComposite addFeatureTreeEditor(Composite composite_3) {
167 FeatureTreeEditorComposite featureTreeEditorComposite = new FeatureTreeEditorComposite(composite_3, SWT.NONE);
168 featureTreeEditorComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
169 return featureTreeEditorComposite;
170 }
171
172 private void initFeatureTreeComposite(FeatureTreeEditorComposite featureTreeEditorComposite,
173 FeatureNodeDragListener featureNodeDragListener, FeatureNodeDropAdapter featureNodeDropAdapter) {
174 featureTreeEditorComposite.init(featureNodeDragListener, featureNodeDropAdapter, this,
175 new FeatureTreeChooserListener(featureTreeEditorComposite));
176 }
177
178 @Focus
179 public void focus(){
180 if(characterTreeEditorComposite!=null){
181 characterTreeEditorComposite.getViewer().getControl().setFocus();
182 }
183 if(conversation!=null && !conversation.isBound()){
184 conversation.bind();
185 }
186 if(cdmEntitySession != null) {
187 cdmEntitySession.bind();
188 }
189 }
190
191 private void init(){
192 btnAddCharacter.addSelectionListener(new SelectionAdapter() {
193 /**
194 * {@inheritDoc}
195 */
196 @Override
197 public void widgetSelected(SelectionEvent e) {
198 ISelection structureTreeSelection = structuresTreeEditorComposite.getViewer().getSelection();
199 ISelection propertyTreeSelection = propertiesTreeEditorComposite.getViewer().getSelection();
200 if(structureTreeSelection==null || propertyTreeSelection==null || characterTreeEditorComposite.getFeatureTree()==null){
201 MessagingUtils.warningDialog("Cannot perform action", CharacterEditor.this,
202 "You have to select a structure, a property and a feature tree to perform this action.");
203 return;
204 }
205 //get selected structures and properties
206 Iterator<FeatureNode> structureIterator = ((TreeSelection)structureTreeSelection).iterator();
207
208 //create all combinations of structures and properties
209 while(structureIterator.hasNext()){
210 FeatureNode structureNode = structureIterator.next();
211 Iterator<FeatureNode> propertiesIterator = ((TreeSelection)propertyTreeSelection).iterator();
212 while(propertiesIterator.hasNext()){
213 FeatureNode propertyNode = propertiesIterator.next();
214 //create new Character
215 String label = structureNode.getFeature().generateTitle()+" "+propertyNode.getFeature().generateTitle();
216 Character character = Character.NewInstance(structureNode, propertyNode, "", label, label);
217 character = HibernateProxyHelper.deproxy(CdmStore.getService(ITermService.class).merge(character), Character.class);
218
219 //add new Character to feature tree
220 FeatureNode parent = ((FeatureTree) characterTreeEditorComposite.getViewer().getInput()).getRoot();
221 CdmStore.getService(IFeatureNodeService.class).addChildFeatureNode(parent.getUuid(), character.getUuid());
222 }
223 }
224
225 setDirty(true);
226 characterTreeEditorComposite.getViewer().refresh();
227 }
228 });
229 }
230
231 @Override
232 @Persist
233 public void save(IProgressMonitor monitor){
234 if (!conversation.isBound()) {
235 conversation.bind();
236 }
237
238 // commit the conversation and start a new transaction immediately
239 conversation.commit(true);
240
241 CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(characterTreeEditorComposite.getFeatureTree());
242
243 this.setDirty(false);
244 }
245
246 @PreDestroy
247 public void dispose(){
248 if(conversation!=null){
249 conversation.close();
250 }
251 if(cdmEntitySession != null) {
252 cdmEntitySession.dispose();
253 }
254 }
255
256 @Override
257 public Map<Object, List<String>> getPropertyPathsMap() {
258 List<String> propertyPaths = Arrays.asList(new String[] {
259 "children", //$NON-NLS-1$
260 "feature", //$NON-NLS-1$
261 "featureTree", //$NON-NLS-1$
262 });
263 Map<Object, List<String>> propertyPathMap =
264 new HashMap<Object, List<String>>();
265 propertyPathMap.put(FeatureNode.class,propertyPaths);
266 return propertyPathMap;
267 }
268
269 /**
270 * {@inheritDoc}
271 */
272 @Override
273 public List<FeatureTree> getRootEntities() {
274 List<FeatureTree> root = new ArrayList<>();
275 root.add(characterTreeEditorComposite.getFeatureTree());
276 return root;
277 }
278
279 @Override
280 public ICdmEntitySession getCdmEntitySession() {
281 return cdmEntitySession;
282 }
283
284 @Focus
285 public void setFocus() {
286 if(conversation!=null && !conversation.isBound()){
287 conversation.bind();
288 }
289 }
290
291 /** {@inheritDoc} */
292 @Override
293 public void selectionChanged(SelectionChangedEvent event) {
294 //propagate selection
295 selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event));
296 }
297
298
299 /**
300 * {@inheritDoc}
301 */
302 @Override
303 public void modifyText(ModifyEvent e) {
304 characterTreeEditorComposite.getFeatureTree().setTitleCache(characterTreeEditorComposite.getText_title().getText(), true);
305 setDirty(true);
306 }
307
308
309 public void setDirty(boolean isDirty) {
310 dirty.setDirty(isDirty);
311 }
312
313 /**
314 * {@inheritDoc}
315 */
316 @Override
317 public IStructuredSelection getSelection() {
318 return (IStructuredSelection) characterTreeEditorComposite.getViewer().getSelection();
319 }
320
321 @Override
322 public void refresh(){
323 structuresTreeEditorComposite.getViewer().refresh();
324 propertiesTreeEditorComposite.getViewer().refresh();
325 characterTreeEditorComposite.getViewer().refresh();
326 }
327
328 private class FeatureTreeChooserListener extends SelectionAdapter{
329 FeatureTreeEditorComposite featureTreeEditorComposite;
330
331 public FeatureTreeChooserListener(FeatureTreeEditorComposite featureTreeEditorComposite) {
332 super();
333 this.featureTreeEditorComposite = featureTreeEditorComposite;
334 }
335
336 @Override
337 public void widgetSelected(SelectionEvent e) {
338 FeatureTree tree = FeatureTreeSelectionDialog.select(featureTreeEditorComposite.getDisplay().getActiveShell(), conversation, null);
339 if(tree!=null){
340 featureTreeEditorComposite.setSelectedTree(tree, CharacterEditor.this);
341 featureTreeEditorComposite.getText_title().setEnabled(false);
342 }
343 }
344 }
345
346 }