Project

General

Profile

Download (20.8 KB) Statistics
| Branch: | Tag: | Revision:
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.descriptiveDataSet.character;
11

    
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.Collection;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Set;
21

    
22
import javax.annotation.PostConstruct;
23
import javax.annotation.PreDestroy;
24
import javax.inject.Inject;
25

    
26
import org.eclipse.core.runtime.IProgressMonitor;
27
import org.eclipse.e4.ui.di.Focus;
28
import org.eclipse.e4.ui.di.Persist;
29
import org.eclipse.e4.ui.di.UISynchronize;
30
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
31
import org.eclipse.e4.ui.services.EMenuService;
32
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
33
import org.eclipse.jface.viewers.ISelection;
34
import org.eclipse.jface.viewers.ISelectionChangedListener;
35
import org.eclipse.jface.viewers.IStructuredSelection;
36
import org.eclipse.jface.viewers.SelectionChangedEvent;
37
import org.eclipse.jface.viewers.StructuredSelection;
38
import org.eclipse.jface.viewers.TreeSelection;
39
import org.eclipse.jface.viewers.TreeViewer;
40
import org.eclipse.swt.SWT;
41
import org.eclipse.swt.custom.SashForm;
42
import org.eclipse.swt.dnd.DND;
43
import org.eclipse.swt.dnd.Transfer;
44
import org.eclipse.swt.events.ModifyEvent;
45
import org.eclipse.swt.events.ModifyListener;
46
import org.eclipse.swt.events.SelectionAdapter;
47
import org.eclipse.swt.events.SelectionEvent;
48
import org.eclipse.swt.layout.GridData;
49
import org.eclipse.swt.layout.GridLayout;
50
import org.eclipse.swt.widgets.Button;
51
import org.eclipse.swt.widgets.Composite;
52
import org.eclipse.swt.widgets.Display;
53
import org.eclipse.swt.widgets.Label;
54
import org.eclipse.swt.widgets.Text;
55
import org.eclipse.ui.forms.widgets.FormToolkit;
56

    
57
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
58
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
59
import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
60
import eu.etaxonomy.cdm.api.service.ITermTreeService;
61
import eu.etaxonomy.cdm.api.service.IVocabularyService;
62
import eu.etaxonomy.cdm.api.service.UpdateResult;
63
import eu.etaxonomy.cdm.model.description.Character;
64
import eu.etaxonomy.cdm.model.description.Feature;
65
import eu.etaxonomy.cdm.model.term.DefinedTerm;
66
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
67
import eu.etaxonomy.cdm.model.term.TermNode;
68
import eu.etaxonomy.cdm.model.term.TermTree;
69
import eu.etaxonomy.cdm.model.term.TermType;
70
import eu.etaxonomy.cdm.model.term.TermVocabulary;
71
import eu.etaxonomy.cdm.model.term.VocabularyEnum;
72
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
73
import eu.etaxonomy.taxeditor.editor.AppModelId;
74
import eu.etaxonomy.taxeditor.editor.definedterm.FeatureTreeViewerComparator;
75
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
76
import eu.etaxonomy.taxeditor.featuretree.CharacterTransfer;
77
import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
78
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeContentProvider;
79
import eu.etaxonomy.taxeditor.featuretree.FeatureTreeLabelProvider;
80
import eu.etaxonomy.taxeditor.featuretree.e4.AbstractTermTreeEditor;
81
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureNodeDragListener;
82
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureTreeDropAdapter;
83
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureTreeEditorComposite;
84
import eu.etaxonomy.taxeditor.featuretree.e4.IFeatureTreeEditor;
85
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
86
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
87
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
88
import eu.etaxonomy.taxeditor.model.ImageResources;
89
import eu.etaxonomy.taxeditor.model.MessagingUtils;
90
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
91
import eu.etaxonomy.taxeditor.store.CdmStore;
92
import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
93
import eu.etaxonomy.taxeditor.ui.dialog.selection.TermVocabularySelectionDialog;
94
import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
95

    
96
/**
97
 * Editor for combining structure and property terms to characters.
98
 * @author pplitzner
99
 * @date 24.05.2017
100
 *
101
 */
102
public class CharacterEditor implements IFeatureTreeEditor,IConversationEnabled, ISelectionChangedListener,
103
        ModifyListener, IE4ViewerPart, IPartContentHasDetails, IPartContentHasSupplementalData, IDirtyMarkable {
104

    
105
    private FeatureTreeEditorComposite<Character> characterTreeEditorComposite;
106
    private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
107

    
108
    @Inject
109
    private ESelectionService selService;
110

    
111
    @Inject
112
    private UISynchronize sync;
113

    
114
    @Inject
115
    private MDirtyable dirty;
116

    
117
    private ConversationHolder conversation;
118

    
119
    private ICdmEntitySession cdmEntitySession;
120

    
121
    private TermVocabulary vocabulary;
122
    private TreeViewer structureViewer;
123
    private TreeViewer propertyViewer;
124

    
125
    public CharacterEditor() {
126
    }
127

    
128
    /**
129
     * Create contents of the view part.
130
     */
131
    @PostConstruct
132
    public void createControls(Composite parent, EMenuService menuService ) {
133
        if (CdmStore.isActive()){
134
            if(conversation == null){
135
                conversation = CdmStore.createConversation();
136
            }
137
            if(cdmEntitySession==null){
138
                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
139
            }
140
        }
141
        else{
142
            return;
143
        }
144
        parent.setLayout(new GridLayout(1, false));
145

    
146
        Composite vocChooserComposite = new Composite(parent, SWT.NONE);
147
        vocChooserComposite.setLayout(new GridLayout(4, false));
148
        vocChooserComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false, 2, 1));
149
        Label lblVocImport = new Label(vocChooserComposite, SWT.NONE);
150
        lblVocImport.setText("Character vocabulary");
151
        Text txtVocabulary = new Text(vocChooserComposite, SWT.NONE);
152
        txtVocabulary.setEditable(false);
153
        Button btnChooseVoc = new Button(vocChooserComposite, SWT.PUSH);
154
        btnChooseVoc.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
155
        btnChooseVoc.addSelectionListener(new SelectionAdapter() {
156

    
157
            @Override
158
            public void widgetSelected(SelectionEvent e) {
159
                // hard-coded filter for "built-in" vocabularies Feature and Name Feature
160
                Set<TermVocabulary> vocabulariesToBeFiltered = new HashSet<>();
161
                vocabulariesToBeFiltered.add(CdmStore.getService(IVocabularyService.class).load(VocabularyEnum.Feature.getUuid()));
162
                vocabulariesToBeFiltered.add(CdmStore.getService(IVocabularyService.class).load(VocabularyEnum.NameFeature.getUuid()));
163
                if(vocabulary!=null){
164
                    vocabulariesToBeFiltered.add(vocabulary);
165
                }
166
                vocabulary = TermVocabularySelectionDialog.select("Select vocabulary for characters", btnChooseVoc.getShell(), vocabulariesToBeFiltered, TermType.Character);
167
                if(vocabulary!=null){
168
                    txtVocabulary.setText(vocabulary.getLabel());
169
                }
170
            }
171
        });
172
//        Button btnRefresh = new Button(vocChooserComposite, SWT.PUSH);
173
//        btnRefresh.setImage(ImageResources.getImage(ImageResources.REFRESH));
174
//        btnRefresh.setToolTipText("Refresh");
175
//        btnRefresh.addSelectionListener(new SelectionAdapter() {
176
//
177
//            @Override
178
//            public void widgetSelected(SelectionEvent e) {
179
//                refresh();
180
//            }
181
//        });
182

    
183
        SashForm sashForm = new SashForm(parent, SWT.NONE);
184
        sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
185
        formToolkit.adapt(sashForm);
186
        formToolkit.paintBordersFor(sashForm);
187

    
188
        Composite composite = new Composite(sashForm, SWT.NONE);
189
        formToolkit.adapt(composite);
190
        formToolkit.paintBordersFor(composite);
191
        GridLayout gl_composite = new GridLayout(1, false);
192
        gl_composite.marginWidth = 0;
193
        composite.setLayout(gl_composite);
194

    
195
        structureViewer = createTreeViewer(composite, TermType.Structure);
196

    
197
        Composite composite_1 = new Composite(sashForm, SWT.NONE);
198
        formToolkit.adapt(composite_1);
199
        formToolkit.paintBordersFor(composite_1);
200
        GridLayout gl_composite_1 = new GridLayout(1, false);
201
        gl_composite_1.marginWidth = 0;
202
        composite_1.setLayout(gl_composite_1);
203

    
204
        propertyViewer = createTreeViewer(composite_1, TermType.Property);
205

    
206
        int ops = DND.DROP_COPY | DND.DROP_MOVE;
207
        Transfer[] transfers = new Transfer[] {CharacterTransfer.getInstance()};
208
        propertyViewer.addDragSupport(ops, transfers, new CharacterDragListener(structureViewer, propertyViewer));
209

    
210
        Composite composite_3 = new Composite(sashForm, SWT.NONE);
211
        formToolkit.adapt(composite_3);
212
        formToolkit.paintBordersFor(composite_3);
213
        GridLayout gl_composite_3 = new GridLayout(2, false);
214
        gl_composite_3.marginWidth = 0;
215
        composite_3.setLayout(gl_composite_3);
216

    
217
        Button btnAddCharacter = new Button(composite_3, SWT.NONE);
218
        btnAddCharacter.setText(">>"); //$NON-NLS-1$
219
        formToolkit.adapt(btnAddCharacter, true, true);
220
        btnAddCharacter.addSelectionListener(new SelectionAdapter() {
221
            @Override
222
            public void widgetSelected(SelectionEvent e) {
223
                if(!isVocabularySet()){
224
                    return;
225
                }
226
                ISelection structureTreeSelection = structureViewer.getSelection();
227
                ISelection propertyTreeSelection = propertyViewer.getSelection();
228
                if(structureTreeSelection==null || propertyTreeSelection==null || characterTreeEditorComposite.getFeatureTree()==null){
229
                    MessagingUtils.warningDialog(Messages.CharacterEditor_CANNOT_PERFORM_TITLE, CharacterEditor.this,
230
                            Messages.CharacterEditor_CANNOT_PERFORM_MESSAGE);
231
                    return;
232
                }
233
                Collection<Character> characters = createCharacters((TreeSelection)structureTreeSelection, (TreeSelection)propertyTreeSelection);
234
                TermNode<Character> parent = ((TermTree<Character>) characterTreeEditorComposite.getViewer().getInput()).getRoot();
235
                for (Character character : characters) {
236
                    //add new Character to feature tree
237
                    UpdateResult result = CdmStore.getService(IFeatureNodeService.class).createChildFeatureNode(parent.getUuid(), character, vocabulary.getUuid());
238
                    cdmEntitySession.load(result, true);
239
                }
240
                refresh();
241
            }
242
        });
243

    
244
        characterTreeEditorComposite = addFeatureTreeEditor(composite_3);
245
        initFeatureTreeComposite(TermType.Character, characterTreeEditorComposite, new FeatureNodeDragListener(characterTreeEditorComposite.getViewer()),
246
                new CharacterDropAdapter(this, characterTreeEditorComposite.getViewer(), sync),
247

    
248
                new Transfer[] {FeatureNodeTransfer.getInstance(), CharacterTransfer.getInstance()},
249
                this,
250
                this);
251

    
252
        characterTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_CHARACTERS);
253

    
254
        //add context menu to character viewer
255
        menuService.registerContextMenu(characterTreeEditorComposite.getViewer().getControl(),
256
                AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_EDITOR_POPUPMENU_CHARACTEREDITOR);
257

    
258
    }
259

    
260
    private TreeViewer createTreeViewer(Composite parent, TermType termType) {
261
        Composite composite = new Composite(parent, SWT.NONE);
262
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
263
        composite.setLayout(new GridLayout(2, false));
264
        Label label = new Label(composite, SWT.NONE);
265
        label.setText(termType.getMessage());
266
        Button btnRefresh = new Button(composite, SWT.PUSH);
267
        btnRefresh.setImage(ImageResources.getImage(ImageResources.REFRESH));
268
        btnRefresh.setToolTipText("Refresh");
269

    
270

    
271
        TreeViewer viewer = new TreeViewer(composite);
272
        viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
273
        viewer.setContentProvider(new FeatureTreeContentProvider());
274
        viewer.setLabelProvider(new FeatureTreeLabelProvider());
275
        viewer.setComparator(new FeatureTreeViewerComparator());
276
        viewer.addSelectionChangedListener(this);
277
        viewer.setInput(CdmStore.getService(ITermTreeService.class).list(termType, null, null, null, AbstractTermTreeEditor.TREE_PROPERTY_PATH));
278
        btnRefresh.addSelectionListener(new SelectionAdapter() {
279

    
280
            @Override
281
            public void widgetSelected(SelectionEvent e) {
282
                refresh(viewer);
283
            }
284
        });
285
        return viewer;
286
    }
287

    
288
    private <T extends DefinedTermBase> FeatureTreeEditorComposite<T> addFeatureTreeEditor(Composite composite_3) {
289
        FeatureTreeEditorComposite<T> featureTreeEditorComposite = new FeatureTreeEditorComposite<>(composite_3, SWT.NONE);
290
        featureTreeEditorComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
291
        return featureTreeEditorComposite;
292
    }
293

    
294
    private void initFeatureTreeComposite(
295
            TermType termType,
296
            FeatureTreeEditorComposite featureTreeEditorComposite,
297
            FeatureNodeDragListener featureNodeDragListener,
298
            FeatureTreeDropAdapter featureNodeDropAdapter,
299
            Transfer[] transfers,
300
            ISelectionChangedListener viewerSelectionChangedListener,
301
            ModifyListener modifyListener) {
302

    
303
        featureTreeEditorComposite.init(
304
                featureNodeDragListener,
305
                featureNodeDropAdapter,
306
                transfers,
307
                viewerSelectionChangedListener,
308
                new FeatureTreeChooserListener(featureTreeEditorComposite, termType),
309
                modifyListener);
310
    }
311

    
312
    @Focus
313
    public void focus(){
314
        if(characterTreeEditorComposite!=null){
315
            characterTreeEditorComposite.getViewer().getControl().setFocus();
316
        }
317
        if(conversation!=null && !conversation.isBound()){
318
            conversation.bind();
319
        }
320
        if(cdmEntitySession != null) {
321
            cdmEntitySession.bind();
322
        }
323
    }
324

    
325
    public static Collection<Character> createCharacters(TreeSelection structureTreeSelection, TreeSelection propertyTreeSelection){
326
        Set<Character> characters = new HashSet<>();
327
        //get selected structures and properties
328
        Iterator<TermNode<DefinedTerm>> structureIterator = structureTreeSelection.iterator();
329

    
330
        //create all combinations of structures and properties
331
        while(structureIterator.hasNext()){
332
            TermNode<DefinedTerm> structureNode = structureIterator.next();
333
            Iterator<TermNode<DefinedTerm>> propertiesIterator = propertyTreeSelection.iterator();
334
            while(propertiesIterator.hasNext()){
335
                TermNode<DefinedTerm> propertyNode = propertiesIterator.next();
336
                Character character = CharacterTransfer.createCharacter(structureNode, propertyNode);
337
                characters.add(character);
338

    
339
            }
340
        }
341
        return characters;
342
    }
343

    
344
    @Override
345
    @Persist
346
    public void save(IProgressMonitor monitor){
347
        if (!conversation.isBound()) {
348
            conversation.bind();
349
        }
350

    
351
        TermTree<Character> featureTree = characterTreeEditorComposite.getFeatureTree();
352

    
353
        CdmStore.getService(ITermTreeService.class).merge(featureTree, true);
354

    
355
        // commit the conversation and start a new transaction immediately
356
        conversation.commit(true);
357

    
358
        initializeTrees();
359

    
360
        dirty.setDirty(false);
361
    }
362

    
363
    private void initializeTrees() {
364
        Object[] expandedElements = characterTreeEditorComposite.getViewer().getExpandedElements();
365
        characterTreeEditorComposite.getViewer().getTree().removeAll();
366
        TermTree tree = (TermTree) characterTreeEditorComposite.getViewer().getInput();
367
        cdmEntitySession.load(tree, true);
368
        characterTreeEditorComposite.getViewer().setInput(tree);
369
        characterTreeEditorComposite.getViewer().setExpandedElements(expandedElements);
370
    }
371

    
372
    @Override
373
    public boolean isDirty() {
374
        return dirty.isDirty();
375
    }
376

    
377
    @PreDestroy
378
    public void dispose(){
379
        if(conversation!=null){
380
            conversation.close();
381
            conversation = null;
382
        }
383
        if(cdmEntitySession != null) {
384
            cdmEntitySession.dispose();
385
            cdmEntitySession = null;
386
        }
387
        dirty.setDirty(false);
388
    }
389

    
390
    public boolean isVocabularySet() {
391
        if(vocabulary==null){
392
            MessagingUtils.warningDialog("Character creation not possible", this.getClass(), "Please select a vocabulary for the characters.");
393
        }
394
        return vocabulary!=null;
395
    }
396

    
397
    public TermVocabulary getVocabulary() {
398
        return vocabulary;
399
    }
400

    
401
    @Override
402
    public Map<Object, List<String>> getPropertyPathsMap() {
403
        List<String> propertyPaths = Arrays.asList(new String[] {
404
                "children", //$NON-NLS-1$
405
                "feature", //$NON-NLS-1$
406
                "featureTree", //$NON-NLS-1$
407
        });
408
        Map<Object, List<String>> propertyPathMap =
409
                new HashMap<Object, List<String>>();
410
        propertyPathMap.put(TermNode.class,propertyPaths);
411
        return propertyPathMap;
412
    }
413

    
414
    @Override
415
    public List<TermTree<Character>> getRootEntities() {
416
        List<TermTree<Character>> root = new ArrayList<>();
417
        cdmEntitySession.load(characterTreeEditorComposite.getFeatureTree(), true);
418
        root.add(characterTreeEditorComposite.getFeatureTree());
419
        return root;
420
    }
421

    
422
    @Override
423
    public ICdmEntitySession getCdmEntitySession() {
424
        return cdmEntitySession;
425
    }
426

    
427
    @Focus
428
    public void setFocus() {
429
        if(conversation!=null && !conversation.isBound()){
430
            conversation.bind();
431
        }
432
    }
433

    
434
    @Override
435
    public void selectionChanged(SelectionChangedEvent event) {
436
        //propagate selection
437
        selService.setSelection(event.getSelection());
438
    }
439

    
440

    
441
    @Override
442
    public void modifyText(ModifyEvent e) {
443
        characterTreeEditorComposite.getFeatureTree().setTitleCache(((Text) e.widget).getText(), true);
444
        setDirty();
445
    }
446

    
447

    
448
    private void setDirty() {
449
        dirty.setDirty(true);
450
    }
451

    
452
    @Override
453
    public IStructuredSelection getSelection() {
454
        return (IStructuredSelection) characterTreeEditorComposite.getViewer().getSelection();
455
    }
456

    
457
    @Override
458
    public TermType getTermType() {
459
        return TermType.Character;
460
    }
461

    
462
    public TermTree<Character> getCharacterTree(){
463
        return characterTreeEditorComposite.getFeatureTree();
464
    }
465

    
466

    
467
    public void refresh(TreeViewer viewer){
468
        viewer.refresh();
469

    
470
        characterTreeEditorComposite.getViewer().setInput(characterTreeEditorComposite.getViewer().getInput());
471
    }
472

    
473
    private class FeatureTreeChooserListener extends SelectionAdapter{
474
        private FeatureTreeEditorComposite<Feature> featureTreeEditorComposite;
475
        private TermType termType;
476

    
477
        public FeatureTreeChooserListener(FeatureTreeEditorComposite<Feature> featureTreeEditorComposite, TermType termType) {
478
            super();
479
            this.featureTreeEditorComposite = featureTreeEditorComposite;
480
            this.termType = termType;
481
        }
482

    
483
        @Override
484
        public void widgetSelected(SelectionEvent e) {
485
            TermTree tree = FeatureTreeSelectionDialog.select(featureTreeEditorComposite.getDisplay().getActiveShell(), null, termType);
486
            if(tree!=null){
487
//                cdmEntitySession.load(tree, true);
488
                featureTreeEditorComposite.setSelectedTree(tree);
489
            }
490
        }
491
    }
492

    
493
    @Override
494
    public void update(CdmDataChangeMap arg0) {
495
    }
496

    
497
    @Override
498
    public ConversationHolder getConversationHolder() {
499
        return conversation;
500
    }
501

    
502
    @Override
503
    public void changed(Object element) {
504
        setDirty();
505
        characterTreeEditorComposite.getViewer().refresh();
506
    }
507

    
508
    @Override
509
    public void forceDirty() {
510
        setDirty();
511
    }
512

    
513
    @Override
514
    public boolean postOperation(Object objectAffectedByOperation) {
515
        characterTreeEditorComposite.getViewer().refresh();
516
        if(objectAffectedByOperation instanceof TermNode){
517
            StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
518
            characterTreeEditorComposite.getViewer().setSelection(selection);
519
        }
520
        return true;
521
    }
522

    
523
    @Override
524
    public boolean onComplete() {
525
        return false;
526
    }
527

    
528
    @Override
529
    public void refresh() {
530
        structureViewer.refresh();
531
        propertyViewer.refresh();
532
        characterTreeEditorComposite.getViewer().setInput(characterTreeEditorComposite.getViewer().getInput());
533

    
534
    }
535

    
536
}
(3-3/3)