Project

General

Profile

Download (16.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2007 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

    
10
package eu.etaxonomy.taxeditor.bulkeditor.e4;
11

    
12
import java.util.EventObject;
13
import java.util.List;
14

    
15
import javax.annotation.PostConstruct;
16
import javax.annotation.PreDestroy;
17
import javax.inject.Inject;
18

    
19
import org.eclipse.core.runtime.IProgressMonitor;
20
import org.eclipse.core.runtime.NullProgressMonitor;
21
import org.eclipse.e4.core.services.events.IEventBroker;
22
import org.eclipse.e4.ui.di.Focus;
23
import org.eclipse.e4.ui.di.Persist;
24
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
25
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
26
import org.eclipse.e4.ui.services.EMenuService;
27
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
28
import org.eclipse.jface.dialogs.MessageDialog;
29
import org.eclipse.jface.layout.GridDataFactory;
30
import org.eclipse.jface.viewers.ArrayContentProvider;
31
import org.eclipse.jface.viewers.CellEditor;
32
import org.eclipse.jface.viewers.ColumnViewerEditor;
33
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
34
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
35
import org.eclipse.jface.viewers.ICellModifier;
36
import org.eclipse.jface.viewers.ISelection;
37
import org.eclipse.jface.viewers.ISelectionChangedListener;
38
import org.eclipse.jface.viewers.IStructuredSelection;
39
import org.eclipse.jface.viewers.ITableLabelProvider;
40
import org.eclipse.jface.viewers.TableViewer;
41
import org.eclipse.jface.viewers.TableViewerColumn;
42
import org.eclipse.jface.viewers.TableViewerEditor;
43
import org.eclipse.jface.viewers.TableViewerFocusCellManager;
44
import org.eclipse.jface.viewers.TextCellEditor;
45
import org.eclipse.nebula.widgets.nattable.NatTable;
46
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
47
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
48
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
49
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
50
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
51
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
52
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
53
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
54
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
55
import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
56
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
57
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
58
import org.eclipse.nebula.widgets.nattable.layer.ILayer;
59
import org.eclipse.nebula.widgets.nattable.layer.stack.DefaultBodyLayerStack;
60
import org.eclipse.swt.SWT;
61
import org.eclipse.swt.events.MouseEvent;
62
import org.eclipse.swt.layout.FillLayout;
63
import org.eclipse.swt.layout.GridData;
64
import org.eclipse.swt.layout.GridLayout;
65
import org.eclipse.swt.widgets.Composite;
66
import org.eclipse.swt.widgets.Table;
67

    
68
import ca.odell.glazedlists.BasicEventList;
69
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
70
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
71
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
72
import eu.etaxonomy.cdm.model.common.CdmBase;
73
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
74
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
75
import eu.etaxonomy.cdm.model.taxon.Taxon;
76
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
77
import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorQuery;
78
import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
79
import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
80
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
81
import eu.etaxonomy.taxeditor.l10n.Messages;
82
import eu.etaxonomy.taxeditor.model.AbstractUtility;
83
import eu.etaxonomy.taxeditor.model.IDerivedUnitFacadePart;
84
import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
85
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
86
import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
87
import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
88
import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
89
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
90
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
91

    
92
/**
93
 *
94
 * @author pplitzner
95
 * @since Sep 8, 2017
96
 *
97
 */
98
public class BulkEditorE4 implements IPartContentHasDetails, IConversationEnabled, IPostOperationEnabled,
99
        IDirtyMarkable, IDerivedUnitFacadePart, IPartContentHasFactualData,
100
        IPartContentHasSupplementalData, IPartContentHasMedia, IE4SavablePart, ITaxonEditor {
101

    
102
	@Inject
103
	private MDirtyable dirty;
104

    
105
    private AbstractBulkEditorInput<?> input;
106

    
107
    private Composite topComposite;
108

    
109
    private TableViewer viewer;
110

    
111
    private NatTable natTable;
112

    
113
    private ConversationHolder conversation;
114

    
115
    @Inject
116
    private ESelectionService selService;
117

    
118
    @Inject
119
    private IEventBroker eventBroker;
120

    
121
    private ISelectionChangedListener selectionChangedListener;
122

    
123
    @Inject
124
    private MPart thisPart;
125

    
126
    private BulkEditorQuery lastQuery = null;
127

    
128
    private BasicEventList<Object> list;
129

    
130
    @Inject
131
    public BulkEditorE4() {
132
	}
133

    
134
	public void init(AbstractBulkEditorInput<?> input){
135
	    this.input = input;
136
	    this.conversation = input.getConversation();
137

    
138
	    BulkEditorSearchE4 searchBar = new BulkEditorSearchE4(this, topComposite, SWT.NONE);
139
	    //layout needed because the search bar is added after @PostConstuct method
140
	    topComposite.getParent().layout();
141

    
142
	    thisPart.setLabel(input.getEditorName());
143

    
144
	    //create columns
145
	    Table table = viewer.getTable();
146
	    String[] titles = {input.getName(), "Type"};
147
	    int[] bounds = {500, 100};
148

    
149
	    ColumnViewerEditorActivationStrategy activationSupport = new ColumnViewerEditorActivationStrategy(viewer) {
150
            @Override
151
            protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
152
                // Enable editor only with mouse double click
153
                if (event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION) {
154
                    EventObject source = event.sourceEvent;
155
                    if (source instanceof MouseEvent && ((MouseEvent)source).button == 3) {
156
                        return false;
157
                    }
158

    
159
                    return true;
160
                }
161

    
162
                return false;
163
            }
164
        };
165
        TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(viewer, new BulkEditorFocusCellOwnerDrawHighLighter(viewer));
166

    
167
        TableViewerEditor.create(viewer, focusCellManager, activationSupport, ColumnViewerEditor.TABBING_HORIZONTAL |
168
                ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR |
169
                ColumnViewerEditor.TABBING_VERTICAL |
170
                ColumnViewerEditor.KEYBOARD_ACTIVATION );
171

    
172
	    CellEditor[] editors = new CellEditor[titles.length];
173
	    for (int i = 0; i < titles.length; i++) {
174
	        TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
175
	        editors[i] = new TextCellEditor(table);
176

    
177
	        column.getColumn().setText(titles[i]);
178
	        column.getColumn().setWidth(bounds[i]);
179
	        column.getColumn().setResizable(true);
180
	        column.getColumn().setMoveable(true);
181

    
182
	    }
183

    
184
	    table.setHeaderVisible(true);
185
	    table.setLinesVisible(true);
186

    
187
	    viewer.setCellEditors(editors);
188
	    viewer.setColumnProperties(titles);
189

    
190
	    //content and label provider (NOTE: has to be set AFTER creating cell editors
191
	    viewer.setContentProvider(new ArrayContentProvider());
192
        BulkEditorLabelProvider labelProvider = new BulkEditorLabelProvider(this);
193
        viewer.setLabelProvider(labelProvider);
194

    
195

    
196
        //allow text selection
197
        viewer.setCellModifier(new ICellModifier() {
198
            @Override
199
            public void modify(Object element, String property, Object value) {
200
            }
201
            @Override
202
            public Object getValue(Object element, String property) {
203
                ITableLabelProvider tableLabelProvider = null;
204
                if(viewer.getLabelProvider() instanceof ITableLabelProvider){
205
                    tableLabelProvider = (ITableLabelProvider) viewer.getLabelProvider();
206
                }
207
                Object[] columnProperties = viewer.getColumnProperties();
208
                for (int i=0;i<columnProperties.length;i++) {
209
                    if(columnProperties[i].equals(property) && tableLabelProvider!=null){
210
                        return tableLabelProvider.getColumnText(element, i);
211
                    }
212
                }
213
                return "";
214
            }
215
            @Override
216
            public boolean canModify(Object element, String property) {
217
                return true;
218
            }
219
        });
220

    
221

    
222

    
223
        if(input.getEntityUuid()!=null){
224
            performSearch(new BulkEditorQuery(input.getEntityUuid().toString(), null));
225
        }
226
	}
227

    
228
	/** {@inheritDoc} */
229
	@PostConstruct
230
	public void createPartControl(Composite parent, EMenuService menuService) {
231
		parent.setLayout(new GridLayout());
232

    
233
		topComposite = new Composite(parent, SWT.NONE);
234
		topComposite.setLayout(new GridLayout());
235

    
236
		GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
237
		topComposite.setLayoutData(gridData);
238

    
239
		Composite bottomComposite = new Composite(parent, SWT.NONE);
240
		bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
241
		bottomComposite.setLayout(new FillLayout());
242

    
243

    
244
		//++++NatTable++++
245
		natTable = new NatTable(parent, false);
246
		list = new BasicEventList<>();
247
        ListDataProvider<Object> dataProvider = new ListDataProvider<>(list, new ReflectiveColumnPropertyAccessor<>("titleCache"));
248
        DataLayer dataLayer = new DataLayer(dataProvider);
249
        GlazedListsEventLayer eventLayer = new GlazedListsEventLayer<>(dataLayer, list);
250
        DefaultBodyLayerStack bodyLayerStack = new DefaultBodyLayerStack(eventLayer);
251

    
252
        /**
253
         * column header layer
254
         */
255
        IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(new String[] {"titleCache"});
256
        DataLayer columnHeaderDataLayer = new DataLayer(columnHeaderDataProvider);
257
        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayerStack, bodyLayerStack.getSelectionLayer());
258

    
259
        /**
260
         * row header layer
261
         */
262
        IDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(dataProvider);
263
        DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
264

    
265

    
266
        /**
267
         * corner layer
268
         */
269
        ILayer cornerLayer = new CornerLayer(
270
                new DataLayer(new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider)),
271
                rowHeaderDataLayer, rowHeaderDataLayer);
272

    
273

    
274
        /**
275
         * GRID layer (composition of all other layers)
276
         */
277
        GridLayer gridLayer = new GridLayer(bodyLayerStack, columnHeaderLayer, rowHeaderDataLayer, cornerLayer);
278

    
279
        natTable.setLayer(gridLayer);
280

    
281
        natTable.configure();
282

    
283
        GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
284

    
285

    
286

    
287

    
288

    
289

    
290

    
291

    
292

    
293

    
294

    
295

    
296

    
297
		viewer = new TableViewer(bottomComposite, SWT.MULTI | SWT.FULL_SELECTION);
298

    
299
//		createColumns(viewer);
300

    
301
        //propagate selection
302
        selectionChangedListener = (event -> selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event)));
303
        viewer.addSelectionChangedListener(selectionChangedListener);
304

    
305
        //create context menu
306
        menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.bulkeditor.popupmenu.bulkeditor"); //$NON-NLS-1$
307

    
308
	}
309

    
310
	@Override
311
	@Persist
312
	public void save(IProgressMonitor monitor) {
313
	    save(monitor, true);
314
	}
315

    
316
	@Focus
317
	public void setFocus() {
318
	    //make sure to bind again if maybe in another view the conversation was unbound
319
	    eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, this);
320
	}
321

    
322
	@PreDestroy
323
	public void dispose() {
324
	    if(conversation!=null){
325
	        conversation.unregisterForDataStoreChanges(this);
326
	        conversation.close();
327
	    }
328
	    if(input!=null){
329
	        input.dispose();
330
	    }
331
	}
332

    
333
	public void save(IProgressMonitor monitor, boolean resetMerge) {
334
	    if (!input.getCdmEntitySession().isActive()){
335
            input.getCdmEntitySession().bind();
336
        }
337
	    input.saveModel(resetMerge);
338

    
339
	    List<CdmBase> saveCandidates = getEditorInput().getSaveCandidates();
340
	    ISelection selection = getViewer().getSelection();
341

    
342
        dirty.setDirty(false);
343
        getEditorInput().resetSaveCandidates();
344
        getEditorInput().dispose();
345
        getEditorInput().bind();
346
        conversation.commit(true);
347

    
348
        if (lastQuery != null){
349
            performSearch(lastQuery);
350
            getViewer().setSelection(selection, true);
351
        }
352
        viewer.refresh();
353

    
354

    
355
	}
356

    
357
	/** {@inheritDoc} */
358
    public void performSearch(BulkEditorQuery query) {
359
        if (query != null) {
360

    
361
            // TODO check if dirty, prompt save
362
            if (isDirty()) {
363
                String[] labels = {Messages.BulkEditorE4_SAVE_AND_SEARCH, Messages.BulkEditorE4_DONT_SAVE,Messages.BulkEditorE4_CANCEL};
364
                MessageDialog dialog =new MessageDialog(topComposite.getShell(), Messages.BulkEditorE4_SAVE_CHANGES_TITLE, null, Messages.BulkEditorE4_SAVE_CHANGES_MESSAGE, MessageDialog.QUESTION,labels, 0);
365
                int result = dialog.open();
366
                if (result == 0) {
367
                    save(new NullProgressMonitor());
368
                } else if (result == 2){
369
                    return;
370
                }
371
            }
372
            dirty.setDirty(false);
373
//            getEditorInput().dispose();
374
//            getEditorInput().bind();
375
            getEditorInput().performSearch(query);
376
            lastQuery = query;
377
            List model = getEditorInput().getModel();
378
            viewer.setInput(model);
379
            list.clear();
380
            list.addAll(model);
381

    
382
            refresh();
383
        }
384
    }
385

    
386
    public void refresh() {
387
        refresh(true);
388
    }
389

    
390
    public void refresh(boolean resetInput) {
391
        if(resetInput){
392
            viewer.setInput(getEditorInput().getModel());
393
        }
394
        viewer.refresh();
395
    }
396

    
397
    public TableViewer getViewer() {
398
        return viewer;
399
    }
400

    
401
    public void setDirty(){
402
        dirty.setDirty(true);
403
    }
404

    
405
    public boolean isDirty() {
406
        return dirty.isDirty();
407
    }
408

    
409
    public AbstractBulkEditorInput getEditorInput() {
410
        return input;
411
    }
412

    
413
    /**
414
     * {@inheritDoc}
415
     */
416
    @Override
417
    public void update(CdmDataChangeMap arg0) {
418
    }
419

    
420
    /**
421
     * {@inheritDoc}
422
     */
423
    @Override
424
    public boolean canAttachMedia() {
425
        return true;
426
    }
427

    
428
    /**
429
     * {@inheritDoc}
430
     */
431
    @Override
432
    public void changed(Object element) {
433
        if(element instanceof DerivedUnitFacade){
434
            DerivedUnit derivedUnit = ((DerivedUnitFacade) element).innerDerivedUnit();
435
            if(derivedUnit!=null){
436
                getEditorInput().addSaveCandidate(derivedUnit);
437
            }
438
            FieldUnit fieldUnit = ((DerivedUnitFacade) element).innerFieldUnit();
439
            if(fieldUnit!=null){
440
                getEditorInput().addSaveCandidate(fieldUnit);
441
            }
442
        }
443
        else if (element instanceof CdmBase) {
444
            getEditorInput().addSaveCandidate((CdmBase)element);
445
        }
446
        dirty.setDirty(true);
447
    }
448

    
449
    /**
450
     * {@inheritDoc}
451
     */
452
    @Override
453
    public void forceDirty() {
454
        dirty.setDirty(true);
455
    }
456

    
457
    /**
458
     * {@inheritDoc}
459
     */
460
    @Override
461
    public boolean postOperation(CdmBase objectAffectedByOperation) {
462
        return false;
463
    }
464

    
465
    /**
466
     * {@inheritDoc}
467
     */
468
    @Override
469
    public boolean onComplete() {
470
        return false;
471
    }
472

    
473
    /**
474
     * {@inheritDoc}
475
     */
476
    @Override
477
    public ConversationHolder getConversationHolder() {
478
        return conversation;
479
    }
480

    
481
    /**
482
     * @return
483
     */
484
    public BulkEditorQuery getLastQuery() {
485
       return lastQuery;
486
    }
487

    
488
    /**
489
     * @param object
490
     */
491
    public void setLastQuery(BulkEditorQuery lastQuery) {
492
       this.lastQuery = lastQuery;
493

    
494
    }
495

    
496
    /**
497
     * {@inheritDoc}
498
     */
499
    @Override
500
    public Taxon getTaxon() {
501
        ISelection selection = viewer.getSelection();
502
        if(selection instanceof IStructuredSelection
503
                && ((IStructuredSelection) selection).size()==1) {
504
            Object object = ((IStructuredSelection) selection).iterator().next();
505
            if(object instanceof Taxon){
506
                return (Taxon) object;
507
            }
508
        }
509
        return null;
510
    }
511

    
512
}
(1-1/4)