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