Project

General

Profile

Download (18.5 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.swt.SWT;
40
import org.eclipse.swt.custom.SashForm;
41
import org.eclipse.swt.dnd.Transfer;
42
import org.eclipse.swt.events.ModifyEvent;
43
import org.eclipse.swt.events.ModifyListener;
44
import org.eclipse.swt.events.SelectionAdapter;
45
import org.eclipse.swt.events.SelectionEvent;
46
import org.eclipse.swt.layout.GridData;
47
import org.eclipse.swt.layout.GridLayout;
48
import org.eclipse.swt.widgets.Button;
49
import org.eclipse.swt.widgets.Composite;
50
import org.eclipse.swt.widgets.Display;
51
import org.eclipse.swt.widgets.Label;
52
import org.eclipse.swt.widgets.Text;
53
import org.eclipse.ui.forms.widgets.FormToolkit;
54

    
55
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
56
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
57
import eu.etaxonomy.cdm.api.service.IFeatureNodeService;
58
import eu.etaxonomy.cdm.api.service.IFeatureTreeService;
59
import eu.etaxonomy.cdm.api.service.ITermService;
60
import eu.etaxonomy.cdm.model.common.Representation;
61
import eu.etaxonomy.cdm.model.common.TermVocabulary;
62
import eu.etaxonomy.cdm.model.description.Character;
63
import eu.etaxonomy.cdm.model.description.FeatureNode;
64
import eu.etaxonomy.cdm.model.description.FeatureTree;
65
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
66
import eu.etaxonomy.taxeditor.editor.AppModelId;
67
import eu.etaxonomy.taxeditor.editor.l10n.Messages;
68
import eu.etaxonomy.taxeditor.featuretree.CharacterTransfer;
69
import eu.etaxonomy.taxeditor.featuretree.FeatureNodeTransfer;
70
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureNodeDragListener;
71
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureTreeDropAdapter;
72
import eu.etaxonomy.taxeditor.featuretree.e4.FeatureTreeEditorComposite;
73
import eu.etaxonomy.taxeditor.featuretree.e4.IFeatureTreeEditor;
74
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
75
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
76
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
77
import eu.etaxonomy.taxeditor.model.ImageResources;
78
import eu.etaxonomy.taxeditor.model.MessagingUtils;
79
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
80
import eu.etaxonomy.taxeditor.session.ICdmEntitySession;
81
import eu.etaxonomy.taxeditor.store.CdmStore;
82
import eu.etaxonomy.taxeditor.ui.dialog.selection.FeatureTreeSelectionDialog;
83
import eu.etaxonomy.taxeditor.ui.dialog.selection.TermVocabularySelectionDialog;
84
import eu.etaxonomy.taxeditor.workbench.part.IE4ViewerPart;
85

    
86
/**
87
 * Editor for combining structure and property terms to characters.
88
 * @author pplitzner
89
 * @date 24.05.2017
90
 *
91
 */
92
public class CharacterEditor implements IFeatureTreeEditor,IConversationEnabled, ISelectionChangedListener,
93
        ModifyListener, IE4ViewerPart, IPartContentHasDetails, IPartContentHasSupplementalData, IDirtyMarkable {
94

    
95
    private FeatureTreeEditorComposite characterTreeEditorComposite;
96
    private FeatureTreeEditorComposite propertiesTreeEditorComposite;
97
    private FeatureTreeEditorComposite structuresTreeEditorComposite;
98
    private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
99

    
100
    @Inject
101
    private ESelectionService selService;
102

    
103
    @Inject
104
    private UISynchronize sync;
105

    
106
    @Inject
107
    private MDirtyable dirty;
108

    
109
    private ConversationHolder conversation;
110

    
111
    private ICdmEntitySession cdmEntitySession;
112
    private Composite composite;
113

    
114
    private TermVocabulary vocabulary;
115

    
116
    public CharacterEditor() {
117
    }
118

    
119
    /**
120
     * Create contents of the view part.
121
     */
122
    @PostConstruct
123
    public void createControls(Composite parent, EMenuService menuService ) {
124
        if (CdmStore.isActive()){
125
            if(conversation == null){
126
                conversation = CdmStore.createConversation();
127
            }
128
            if(cdmEntitySession!=null){
129
                cdmEntitySession = CdmStore.getCurrentSessionManager().newSession(this, true);
130
            }
131
        }
132
        else{
133
            return;
134
        }
135
        parent.setLayout(new GridLayout(1, false));
136

    
137
        Composite vocChooserComposite = new Composite(parent, SWT.NONE);
138
        vocChooserComposite.setLayout(new GridLayout(3, false));
139
        vocChooserComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false, 2, 1));
140
        Label lblVocImport = new Label(vocChooserComposite, SWT.NONE);
141
        lblVocImport.setText("Character vocabulary");
142
        Text txtVocabulary = new Text(vocChooserComposite, SWT.NONE);
143
        txtVocabulary.setEditable(false);
144
        Button btnChooseVoc = new Button(vocChooserComposite, SWT.PUSH);
145
        btnChooseVoc.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON));
146
        btnChooseVoc.addSelectionListener(new SelectionAdapter() {
147

    
148
            @Override
149
            public void widgetSelected(SelectionEvent e) {
150
                vocabulary = TermVocabularySelectionDialog.select("Select vocabulary for characters", btnChooseVoc.getShell(), null);
151
                if(vocabulary!=null){
152
                    txtVocabulary.setText(vocabulary.getLabel());
153
                }
154
            }
155
        });
156

    
157
        SashForm sashForm = new SashForm(parent, SWT.NONE);
158
        sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
159
        formToolkit.adapt(sashForm);
160
        formToolkit.paintBordersFor(sashForm);
161

    
162
        composite = new Composite(sashForm, SWT.NONE);
163
        formToolkit.adapt(composite);
164
        formToolkit.paintBordersFor(composite);
165
        GridLayout gl_composite = new GridLayout(1, false);
166
        gl_composite.marginWidth = 0;
167
        composite.setLayout(gl_composite);
168

    
169
        structuresTreeEditorComposite = addFeatureTreeEditor(composite);
170

    
171
        initFeatureTreeComposite(structuresTreeEditorComposite,
172
                new FeatureNodeDragListener(structuresTreeEditorComposite.getViewer()), null, null, null, null);
173

    
174
        structuresTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_STRUCTURES);
175

    
176
        Composite composite_1 = new Composite(sashForm, SWT.NONE);
177
        formToolkit.adapt(composite_1);
178
        formToolkit.paintBordersFor(composite_1);
179
        GridLayout gl_composite_1 = new GridLayout(1, false);
180
        gl_composite_1.marginWidth = 0;
181
        composite_1.setLayout(gl_composite_1);
182

    
183
        propertiesTreeEditorComposite = addFeatureTreeEditor(composite_1);
184
        initFeatureTreeComposite(propertiesTreeEditorComposite,
185

    
186
                new CharacterDragListener(structuresTreeEditorComposite.getViewer(), propertiesTreeEditorComposite.getViewer()),
187
                null,
188
                new Transfer[] {CharacterTransfer.getInstance()},
189
                null,
190
                null
191

    
192
        );
193
        propertiesTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_PROPERTIES);
194

    
195
        Composite composite_3 = new Composite(sashForm, SWT.NONE);
196
        formToolkit.adapt(composite_3);
197
        formToolkit.paintBordersFor(composite_3);
198
        GridLayout gl_composite_3 = new GridLayout(2, false);
199
        gl_composite_3.marginWidth = 0;
200
        composite_3.setLayout(gl_composite_3);
201

    
202
        Button btnAddCharacter = new Button(composite_3, SWT.NONE);
203
        btnAddCharacter.setText(">>"); //$NON-NLS-1$
204
        formToolkit.adapt(btnAddCharacter, true, true);
205
        btnAddCharacter.addSelectionListener(new SelectionAdapter() {
206
            @Override
207
            public void widgetSelected(SelectionEvent e) {
208
                if(!isVocabularySet()){
209
                    return;
210
                }
211
                ISelection structureTreeSelection = structuresTreeEditorComposite.getViewer().getSelection();
212
                ISelection propertyTreeSelection = propertiesTreeEditorComposite.getViewer().getSelection();
213
                if(structureTreeSelection==null || propertyTreeSelection==null || characterTreeEditorComposite.getFeatureTree()==null){
214
                    MessagingUtils.warningDialog(Messages.CharacterEditor_CANNOT_PERFORM_TITLE, CharacterEditor.this,
215
                            Messages.CharacterEditor_CANNOT_PERFORM_MESSAGE);
216
                    return;
217
                }
218
                Collection<Character> characters = createCharacters((TreeSelection)structureTreeSelection, (TreeSelection)propertyTreeSelection);
219
                for (Character character : characters) {
220
                    //add new Character to feature tree
221
                    FeatureNode parent = ((FeatureTree) characterTreeEditorComposite.getViewer().getInput()).getRoot();
222
                    vocabulary.addTerm(character);
223
                    CdmStore.getService(IFeatureNodeService.class).createChildFeatureNode(parent, character);
224
                }
225
                characterTreeEditorComposite.getViewer().refresh();
226
            }
227
        });
228

    
229
        characterTreeEditorComposite = addFeatureTreeEditor(composite_3);
230
        initFeatureTreeComposite(characterTreeEditorComposite, new FeatureNodeDragListener(characterTreeEditorComposite.getViewer()),
231
                new CharacterDropAdapter(this, characterTreeEditorComposite.getViewer(), sync),
232

    
233
                new Transfer[] {FeatureNodeTransfer.getInstance(), CharacterTransfer.getInstance()},
234
                this,
235
                this);
236

    
237
        characterTreeEditorComposite.getLabel_title().setText(Messages.CharacterEditor_CHARACTERS);
238

    
239
        //add context menu to character viewer
240
        menuService.registerContextMenu(characterTreeEditorComposite.getViewer().getControl(),
241
                AppModelId.POPUPMENU_EU_ETAXONOMY_TAXEDITOR_EDITOR_POPUPMENU_CHARACTEREDITOR);
242

    
243
    }
244

    
245
    private FeatureTreeEditorComposite addFeatureTreeEditor(Composite composite_3) {
246
        FeatureTreeEditorComposite featureTreeEditorComposite = new FeatureTreeEditorComposite(composite_3, SWT.NONE);
247
        featureTreeEditorComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
248
        return featureTreeEditorComposite;
249
    }
250

    
251
    private void initFeatureTreeComposite(
252
            FeatureTreeEditorComposite featureTreeEditorComposite,
253
            FeatureNodeDragListener featureNodeDragListener,
254
            FeatureTreeDropAdapter featureNodeDropAdapter,
255
            Transfer[] transfers,
256
            ISelectionChangedListener viewerSelectionChangedListener,
257
            ModifyListener modifyListener) {
258

    
259
        featureTreeEditorComposite.init(
260
                featureNodeDragListener,
261
                featureNodeDropAdapter,
262
                transfers,
263
                viewerSelectionChangedListener,
264
                new FeatureTreeChooserListener(featureTreeEditorComposite),
265
                modifyListener);
266
    }
267

    
268
    @Focus
269
    public void focus(){
270
        if(characterTreeEditorComposite!=null){
271
            characterTreeEditorComposite.getViewer().getControl().setFocus();
272
        }
273
        if(conversation!=null && !conversation.isBound()){
274
            conversation.bind();
275
        }
276
        if(cdmEntitySession != null) {
277
            cdmEntitySession.bind();
278
        }
279
    }
280

    
281
    public static Collection<Character> createCharacters(TreeSelection structureTreeSelection, TreeSelection propertyTreeSelection){
282
        Set<Character> characters = new HashSet<>();
283
        //get selected structures and properties
284
        Iterator<FeatureNode> structureIterator = structureTreeSelection.iterator();
285

    
286
        //create all combinations of structures and properties
287
        while(structureIterator.hasNext()){
288
            FeatureNode structureNode = structureIterator.next();
289
            Iterator<FeatureNode> propertiesIterator = propertyTreeSelection.iterator();
290
            while(propertiesIterator.hasNext()){
291
                FeatureNode propertyNode = propertiesIterator.next();
292
                Representation structureRepresentation = structureNode.getFeature().getRepresentation(PreferencesUtil.getGlobalLanguage());
293
                Representation propertyRepresentation = propertyNode.getFeature().getRepresentation(PreferencesUtil.getGlobalLanguage());
294
                String label = null;
295
                String abbrevLabel = null;
296
                if(structureRepresentation.getLabel()!=null && propertyRepresentation.getLabel()!=null){
297
                    label = structureRepresentation.getLabel()+" "+propertyRepresentation.getLabel();
298
                }
299
                if(structureRepresentation.getAbbreviatedLabel()!=null && propertyRepresentation.getAbbreviatedLabel()!=null){
300
                    abbrevLabel = structureRepresentation.getAbbreviatedLabel()+" "+propertyRepresentation.getAbbreviatedLabel();
301
                }
302
                //create new Character
303
                Character character = Character.NewInstance(structureNode, propertyNode, null, label, abbrevLabel);
304
                characters.add(character);
305
            }
306
        }
307
        return characters;
308
    }
309

    
310
    @Override
311
    @Persist
312
    public void save(IProgressMonitor monitor){
313
        if (!conversation.isBound()) {
314
            conversation.bind();
315
        }
316

    
317
        // commit the conversation and start a new transaction immediately
318
        conversation.commit(true);
319

    
320
        FeatureTree featureTree = characterTreeEditorComposite.getFeatureTree();
321
        if(featureTree!=null){
322
            //save characters because they can be modified in this editor
323
            featureTree.getDistinctFeatures().forEach(character->CdmStore.getService(ITermService.class).merge(character,true));
324
        }
325
        CdmStore.getService(IFeatureTreeService.class).saveOrUpdate(featureTree);
326

    
327

    
328
        dirty.setDirty(false);
329
    }
330

    
331
    @Override
332
    public boolean isDirty() {
333
        return dirty.isDirty();
334
    }
335

    
336
    @PreDestroy
337
    public void dispose(){
338
        if(conversation!=null){
339
            conversation.close();
340
            conversation = null;
341
        }
342
        if(cdmEntitySession != null) {
343
            cdmEntitySession.dispose();
344
            cdmEntitySession = null;
345
        }
346
        dirty.setDirty(false);
347
    }
348

    
349
    public boolean isVocabularySet() {
350
        if(vocabulary==null){
351
            MessagingUtils.warningDialog("Character creation not possible", this.getClass(), "Please select a vocabulary for the characters.");
352
        }
353
        return vocabulary!=null;
354
    }
355

    
356
    public TermVocabulary getVocabulary() {
357
        return vocabulary;
358
    }
359

    
360
    @Override
361
    public Map<Object, List<String>> getPropertyPathsMap() {
362
        List<String> propertyPaths = Arrays.asList(new String[] {
363
                "children", //$NON-NLS-1$
364
                "feature", //$NON-NLS-1$
365
                "featureTree", //$NON-NLS-1$
366
        });
367
        Map<Object, List<String>> propertyPathMap =
368
                new HashMap<Object, List<String>>();
369
        propertyPathMap.put(FeatureNode.class,propertyPaths);
370
        return propertyPathMap;
371
    }
372

    
373
    @Override
374
    public List<FeatureTree> getRootEntities() {
375
        List<FeatureTree> root = new ArrayList<>();
376
        root.add(characterTreeEditorComposite.getFeatureTree());
377
        return root;
378
    }
379

    
380
    @Override
381
    public ICdmEntitySession getCdmEntitySession() {
382
        return cdmEntitySession;
383
    }
384

    
385
    @Focus
386
    public void setFocus() {
387
        if(conversation!=null && !conversation.isBound()){
388
            conversation.bind();
389
        }
390
    }
391

    
392
    @Override
393
    public void selectionChanged(SelectionChangedEvent event) {
394
        //propagate selection
395
        selService.setSelection(event.getSelection());
396
    }
397

    
398

    
399
    @Override
400
    public void modifyText(ModifyEvent e) {
401
        characterTreeEditorComposite.getFeatureTree().setTitleCache(((Text) e.widget).getText(), true);
402
        setDirty();
403
    }
404

    
405

    
406
    private void setDirty() {
407
        dirty.setDirty(true);
408
    }
409

    
410
    @Override
411
    public IStructuredSelection getSelection() {
412
        return (IStructuredSelection) characterTreeEditorComposite.getViewer().getSelection();
413
    }
414

    
415
    public FeatureTree getCharacterTree(){
416
        return characterTreeEditorComposite.getFeatureTree();
417
    }
418

    
419
    @Override
420
    public void refresh(){
421
        structuresTreeEditorComposite.getViewer().refresh();
422
        propertiesTreeEditorComposite.getViewer().refresh();
423
        characterTreeEditorComposite.getViewer().refresh();
424
    }
425

    
426
    private class FeatureTreeChooserListener extends SelectionAdapter{
427
        FeatureTreeEditorComposite featureTreeEditorComposite;
428

    
429
        public FeatureTreeChooserListener(FeatureTreeEditorComposite featureTreeEditorComposite) {
430
            super();
431
            this.featureTreeEditorComposite = featureTreeEditorComposite;
432
        }
433

    
434
        @Override
435
        public void widgetSelected(SelectionEvent e) {
436
            FeatureTree tree = FeatureTreeSelectionDialog.select(featureTreeEditorComposite.getDisplay().getActiveShell(), //conversation,
437
                    null);
438
            if(tree!=null){
439
                featureTreeEditorComposite.setSelectedTree(tree);
440
                featureTreeEditorComposite.getText_title().setEnabled(false);
441
            }
442
        }
443
    }
444

    
445
    @Override
446
    public void update(CdmDataChangeMap arg0) {
447
    }
448

    
449
    @Override
450
    public ConversationHolder getConversationHolder() {
451
        return conversation;
452
    }
453

    
454
    @Override
455
    public void changed(Object element) {
456
        setDirty();
457
    }
458

    
459
    @Override
460
    public void forceDirty() {
461
        setDirty();
462
    }
463

    
464
    @Override
465
    public boolean postOperation(Object objectAffectedByOperation) {
466
        characterTreeEditorComposite.getViewer().refresh();
467
        if(objectAffectedByOperation instanceof FeatureNode){
468
            StructuredSelection selection = new StructuredSelection(objectAffectedByOperation);
469
            characterTreeEditorComposite.getViewer().setSelection(selection);
470
        }
471
        return true;
472
    }
473

    
474
    @Override
475
    public boolean onComplete() {
476
        return false;
477
    }
478

    
479
}
(3-3/3)