Project

General

Profile

Download (20 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.io.Serializable;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17

    
18
import javax.annotation.PostConstruct;
19
import javax.annotation.PreDestroy;
20
import javax.inject.Inject;
21

    
22
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.NullProgressMonitor;
24
import org.eclipse.e4.core.services.events.IEventBroker;
25
import org.eclipse.e4.ui.di.Focus;
26
import org.eclipse.e4.ui.di.Persist;
27
import org.eclipse.e4.ui.model.application.ui.MDirtyable;
28
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
29
import org.eclipse.e4.ui.services.EMenuService;
30
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
31
import org.eclipse.jface.dialogs.MessageDialog;
32
import org.eclipse.jface.layout.GridDataFactory;
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.StructuredSelection;
37
import org.eclipse.jface.viewers.TableViewer;
38
import org.eclipse.nebula.widgets.nattable.NatTable;
39
import org.eclipse.nebula.widgets.nattable.config.AbstractUiBindingConfiguration;
40
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
41
import org.eclipse.nebula.widgets.nattable.data.IRowIdAccessor;
42
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
43
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
44
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
45
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
46
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
47
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
48
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
49
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
50
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
51
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
52
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
53
import org.eclipse.nebula.widgets.nattable.layer.stack.DefaultBodyLayerStack;
54
import org.eclipse.nebula.widgets.nattable.selection.RowSelectionModel;
55
import org.eclipse.nebula.widgets.nattable.selection.RowSelectionProvider;
56
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
57
import org.eclipse.nebula.widgets.nattable.ui.binding.UiBindingRegistry;
58
import org.eclipse.nebula.widgets.nattable.ui.matcher.MouseEventMatcher;
59
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuAction;
60
import org.eclipse.nebula.widgets.nattable.ui.menu.PopupMenuBuilder;
61
import org.eclipse.swt.SWT;
62
import org.eclipse.swt.layout.GridData;
63
import org.eclipse.swt.layout.GridLayout;
64
import org.eclipse.swt.widgets.Composite;
65
import org.eclipse.swt.widgets.Menu;
66

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

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

    
101
    public static final String TYPE_PROPERTY = "Type";
102

    
103
    @Inject
104
	private MDirtyable dirty;
105

    
106
    private AbstractBulkEditorInput<?> input;
107

    
108
    private Composite topComposite;
109

    
110
    private TableViewer viewer;
111

    
112
    private ConversationHolder conversation;
113

    
114
    @Inject
115
    private ESelectionService selService;
116

    
117
    @Inject
118
    private IEventBroker eventBroker;
119

    
120
    private ISelectionChangedListener selectionChangedListener;
121

    
122
    @Inject
123
    private MPart thisPart;
124

    
125
    private BulkEditorQuery lastQuery = null;
126

    
127
    private Composite bottomComposite;
128

    
129
    @Inject
130
    private EMenuService menuService;
131

    
132
    private NatTable natTable;
133

    
134
    private SelectionLayer selectionLayer;
135

    
136
    private ListDataProvider<CdmBase> bodyDataProvider;
137

    
138
    @Inject
139
    public BulkEditorE4() {
140
	}
141

    
142
	@SuppressWarnings("unused")
143
    public void init(AbstractBulkEditorInput<?> input){
144
	    this.input = input;
145
	    this.conversation = input.getConversation();
146

    
147
	    new BulkEditorSearchE4(this, topComposite, SWT.NONE);
148
	    //layout needed because the search bar is added after @PostConstuct method
149
	    topComposite.getParent().layout();
150

    
151
	    thisPart.setLabel(input.getEditorName());
152

    
153
//	    //create columns
154
//	    Table table = viewer.getTable();
155
//	    String[] titles = {input.getName(), "Type"};
156
//	    int[] bounds = {500, 100};
157
//
158
//	    ColumnViewerEditorActivationStrategy activationSupport = new ColumnViewerEditorActivationStrategy(viewer) {
159
//            @Override
160
//            protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
161
//                // Enable editor only with mouse double click
162
//                if (event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION) {
163
//                    EventObject source = event.sourceEvent;
164
//                    if (source instanceof MouseEvent && ((MouseEvent)source).button == 3) {
165
//                        return false;
166
//                    }
167
//
168
//                    return true;
169
//                }
170
//
171
//                return false;
172
//            }
173
//        };
174
//        TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(viewer, new BulkEditorFocusCellOwnerDrawHighLighter(viewer));
175
//
176
//        TableViewerEditor.create(viewer, focusCellManager, activationSupport, ColumnViewerEditor.TABBING_HORIZONTAL |
177
//                ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR |
178
//                ColumnViewerEditor.TABBING_VERTICAL |
179
//                ColumnViewerEditor.KEYBOARD_ACTIVATION );
180
//
181
//	    CellEditor[] editors = new CellEditor[titles.length];
182
//	    for (int i = 0; i < titles.length; i++) {
183
//	        TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
184
//	        editors[i] = new TextCellEditor(table);
185
//
186
//	        column.getColumn().setText(titles[i]);
187
//	        column.getColumn().setWidth(bounds[i]);
188
//	        column.getColumn().setResizable(true);
189
//	        column.getColumn().setMoveable(true);
190
//
191
//	    }
192
//
193
//	    table.setHeaderVisible(true);
194
//	    table.setLinesVisible(true);
195
//
196
//	    viewer.setCellEditors(editors);
197
//	    viewer.setColumnProperties(titles);
198
//
199
//	    //content and label provider (NOTE: has to be set AFTER creating cell editors
200
//	    viewer.setContentProvider(new ArrayContentProvider());
201
//        BulkEditorLabelProvider labelProvider = new BulkEditorLabelProvider(this);
202
//        viewer.setLabelProvider(labelProvider);
203
//
204
//
205
//        //allow text selection
206
//        viewer.setCellModifier(new ICellModifier() {
207
//            @Override
208
//            public void modify(Object element, String property, Object value) {
209
//            }
210
//            @Override
211
//            public Object getValue(Object element, String property) {
212
//                ITableLabelProvider tableLabelProvider = null;
213
//                if(viewer.getLabelProvider() instanceof ITableLabelProvider){
214
//                    tableLabelProvider = (ITableLabelProvider) viewer.getLabelProvider();
215
//                }
216
//                Object[] columnProperties = viewer.getColumnProperties();
217
//                for (int i=0;i<columnProperties.length;i++) {
218
//                    if(columnProperties[i].equals(property) && tableLabelProvider!=null){
219
//                        return tableLabelProvider.getColumnText(element, i);
220
//                    }
221
//                }
222
//                return "";
223
//            }
224
//            @Override
225
//            public boolean canModify(Object element, String property) {
226
//                return true;
227
//            }
228
//        });
229

    
230

    
231

    
232
        if(input.getEntityUuid()!=null){
233
            performSearch(new BulkEditorQuery(input.getEntityUuid().toString(), null));
234
        }
235

    
236
        //++++NatTable++++
237
        Map<String, String> propertyToLabels = new HashMap<>();
238
        propertyToLabels.put(getEditorInput().getName(), getEditorInput().getName());
239
        propertyToLabels.put(TYPE_PROPERTY, TYPE_PROPERTY);
240
        String[] propertyNames = new String[] { getEditorInput().getName(), TYPE_PROPERTY };
241
        bodyDataProvider = new ListDataProvider<CdmBase>(getEditorInput().getModel(),
242
                new BulkEditorPropertyAccessor(getEditorInput()));
243

    
244

    
245
        DefaultColumnHeaderDataProvider colHeaderDataProvider = new DefaultColumnHeaderDataProvider(
246
                propertyNames, propertyToLabels);
247
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(
248
                bodyDataProvider);
249

    
250
        DataLayer dataLayer = new DataLayer(bodyDataProvider);
251
        GlazedListsEventLayer<CdmBase> eventLayer = new GlazedListsEventLayer<>(dataLayer, getEditorInput().getModel());
252
        DefaultBodyLayerStack bodyLayer = new DefaultBodyLayerStack(eventLayer);
253
        selectionLayer = bodyLayer.getSelectionLayer();
254

    
255
        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(
256
                new DataLayer(colHeaderDataProvider),
257
                bodyLayer, bodyLayer.getSelectionLayer());
258

    
259
        RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(new DataLayer(rowHeaderDataProvider, 50, 20),
260
                bodyLayer, bodyLayer.getSelectionLayer());
261

    
262
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(
263
                colHeaderDataProvider, rowHeaderDataProvider);
264
        CornerLayer cornerLayer = new CornerLayer(new DataLayer(
265
                cornerDataProvider), rowHeaderLayer, columnHeaderLayer);
266

    
267
        GridLayer gridLayer = new GridLayer(bodyLayer, columnHeaderLayer,
268
                rowHeaderLayer, cornerLayer);
269

    
270
        dataLayer.setColumnPercentageSizing(true);
271
        natTable = new NatTable(bottomComposite, gridLayer, false);
272

    
273
        //create context menu
274
        menuService.registerContextMenu(natTable, "eu.etaxonomy.taxeditor.bulkeditor.popupmenu.bulkeditor"); //$NON-NLS-1$
275
        // get the menu registered by EMenuService
276
        final Menu e4Menu = natTable.getMenu();
277

    
278
        // remove the menu reference from NatTable instance
279
        natTable.setMenu(null);
280

    
281
        //add default configuration because autoconfigure is set to false in constructor
282
        natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
283
        natTable.addConfiguration(
284
                new AbstractUiBindingConfiguration() {
285

    
286
            @Override
287
            public void configureUiBindings(
288
                    UiBindingRegistry uiBindingRegistry) {
289
                // add NatTable menu items
290
                // and register the DisposeListener
291
                new PopupMenuBuilder(natTable, e4Menu)
292
                    .build();
293

    
294
                // register the UI binding
295
                uiBindingRegistry.registerMouseDownBinding(
296
                        new MouseEventMatcher(
297
                                SWT.NONE,
298
                                GridRegion.BODY,
299
                                MouseEventMatcher.RIGHT_BUTTON),
300
                        new PopupMenuAction(e4Menu));
301
            }
302
        });
303

    
304
        natTable.configure();
305
        GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
306

    
307
        //full row selection
308
        bodyLayer.getSelectionLayer().setSelectionModel(new RowSelectionModel<CdmBase>(bodyLayer.getSelectionLayer(), bodyDataProvider, new IRowIdAccessor<CdmBase>() {
309

    
310
            @Override
311
            public Serializable getRowId(CdmBase rowObject) {
312
                return getEditorInput().getModel().indexOf(rowObject);
313
            }
314

    
315
        }));
316

    
317
        //propagate selection
318
        selectionChangedListener = (event -> selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event)));
319
        RowSelectionProvider<CdmBase> selectionProvider = new RowSelectionProvider<CdmBase>(selectionLayer, bodyDataProvider, true);
320
        selectionProvider.addSelectionChangedListener(selectionChangedListener);
321
	}
322

    
323
	/** {@inheritDoc} */
324
	@PostConstruct
325
	public void createPartControl(Composite parent) {
326
		parent.setLayout(new GridLayout());
327

    
328
		topComposite = new Composite(parent, SWT.NONE);
329
		topComposite.setLayout(new GridLayout());
330

    
331
		GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
332
		topComposite.setLayoutData(gridData);
333

    
334
		bottomComposite = new Composite(parent, SWT.NONE);
335
		bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
336
		bottomComposite.setLayout(new GridLayout());
337

    
338
//		viewer = new TableViewer(bottomComposite, SWT.MULTI | SWT.FULL_SELECTION);
339

    
340
//		createColumns(viewer);
341

    
342
        //propagate selection
343
        selectionChangedListener = (event -> selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event)));
344
//        viewer.addSelectionChangedListener(selectionChangedListener);
345

    
346
        //create context menu
347
//        menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.bulkeditor.popupmenu.bulkeditor"); //$NON-NLS-1$
348
	}
349

    
350
	@Override
351
	@Persist
352
	public void save(IProgressMonitor monitor) {
353
	    save(monitor, true);
354
	}
355

    
356
	@Focus
357
	public void setFocus() {
358
	    //make sure to bind again if maybe in another view the conversation was unbound
359
	    eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, this);
360
	}
361

    
362
	@PreDestroy
363
	public void dispose() {
364
	    if(conversation!=null){
365
	        conversation.unregisterForDataStoreChanges(this);
366
	        conversation.close();
367
	    }
368
	    if(input!=null){
369
	        input.dispose();
370
	    }
371
	}
372

    
373
	public void save(IProgressMonitor monitor, boolean resetMerge) {
374
	    if (!input.getCdmEntitySession().isActive()){
375
            input.getCdmEntitySession().bind();
376
        }
377
	    input.saveModel(resetMerge);
378

    
379
	    List<CdmBase> saveCandidates = getEditorInput().getSaveCandidates();
380
	    IStructuredSelection selection = getSelection();
381

    
382
        dirty.setDirty(false);
383
        getEditorInput().resetSaveCandidates();
384
        getEditorInput().dispose();
385
        getEditorInput().bind();
386
        conversation.commit(true);
387

    
388
        if (lastQuery != null){
389
            performSearch(lastQuery);
390
            setSelection(selection);
391
        }
392
//        viewer.refresh();
393

    
394

    
395
	}
396

    
397
	/** {@inheritDoc} */
398
    public void performSearch(BulkEditorQuery query) {
399
        if (query != null) {
400

    
401
            // TODO check if dirty, prompt save
402
            if (isDirty()) {
403
                String[] labels = {Messages.BulkEditorE4_SAVE_AND_SEARCH, Messages.BulkEditorE4_DONT_SAVE,Messages.BulkEditorE4_CANCEL};
404
                MessageDialog dialog =new MessageDialog(topComposite.getShell(), Messages.BulkEditorE4_SAVE_CHANGES_TITLE, null, Messages.BulkEditorE4_SAVE_CHANGES_MESSAGE, MessageDialog.QUESTION,labels, 0);
405
                int result = dialog.open();
406
                if (result == 0) {
407
                    save(new NullProgressMonitor());
408
                } else if (result == 2){
409
                    return;
410
                }
411
            }
412
            dirty.setDirty(false);
413
//            getEditorInput().dispose();
414
//            getEditorInput().bind();
415
            getEditorInput().performSearch(query);
416
            lastQuery = query;
417
//            viewer.setInput(model);
418

    
419
            refresh();
420
        }
421
    }
422

    
423
    public void refresh() {
424
        refresh(true);
425
    }
426

    
427
    public void refresh(boolean resetInput) {
428
        if(resetInput){
429
//            viewer.setInput(getEditorInput().getModel());
430
        }
431
//        viewer.refresh();
432
    }
433

    
434
//    public TableViewer getViewer() {
435
//        return viewer;
436
//    }
437

    
438
    public IStructuredSelection getSelection(){
439
        List<CdmBase> selection = new ArrayList<>();
440
        int[] fullySelectedRowPositions = selectionLayer.getFullySelectedRowPositions();
441
        for (int i : fullySelectedRowPositions) {
442
            Object rowObject = bodyDataProvider.getRowObject(i);
443
            if(rowObject instanceof CdmBase){
444
                selection.add((CdmBase) rowObject);
445
            }
446
        }
447
        return new StructuredSelection(selection);
448
    }
449

    
450
    public void setSelection(IStructuredSelection selection){
451
        Object[] objects = selection.toArray();
452
        for (Object object : objects) {
453
            if(object instanceof CdmBase){
454
                selectionLayer.selectRow(0, bodyDataProvider.indexOfRowObject((CdmBase) object), false, false);
455
            }
456
        }
457
    }
458

    
459
    public void setDirty(){
460
        dirty.setDirty(true);
461
    }
462

    
463
    public boolean isDirty() {
464
        return dirty.isDirty();
465
    }
466

    
467
    public AbstractBulkEditorInput getEditorInput() {
468
        return input;
469
    }
470

    
471
    /**
472
     * {@inheritDoc}
473
     */
474
    @Override
475
    public void update(CdmDataChangeMap arg0) {
476
    }
477

    
478
    /**
479
     * {@inheritDoc}
480
     */
481
    @Override
482
    public boolean canAttachMedia() {
483
        return true;
484
    }
485

    
486
    /**
487
     * {@inheritDoc}
488
     */
489
    @Override
490
    public void changed(Object element) {
491
        if(element instanceof DerivedUnitFacade){
492
            DerivedUnit derivedUnit = ((DerivedUnitFacade) element).innerDerivedUnit();
493
            if(derivedUnit!=null){
494
                getEditorInput().addSaveCandidate(derivedUnit);
495
            }
496
            FieldUnit fieldUnit = ((DerivedUnitFacade) element).innerFieldUnit();
497
            if(fieldUnit!=null){
498
                getEditorInput().addSaveCandidate(fieldUnit);
499
            }
500
        }
501
        else if (element instanceof CdmBase) {
502
            getEditorInput().addSaveCandidate((CdmBase)element);
503
        }
504
        dirty.setDirty(true);
505
    }
506

    
507
    /**
508
     * {@inheritDoc}
509
     */
510
    @Override
511
    public void forceDirty() {
512
        dirty.setDirty(true);
513
    }
514

    
515
    /**
516
     * {@inheritDoc}
517
     */
518
    @Override
519
    public boolean postOperation(CdmBase objectAffectedByOperation) {
520
        return false;
521
    }
522

    
523
    /**
524
     * {@inheritDoc}
525
     */
526
    @Override
527
    public boolean onComplete() {
528
        return false;
529
    }
530

    
531
    /**
532
     * {@inheritDoc}
533
     */
534
    @Override
535
    public ConversationHolder getConversationHolder() {
536
        return conversation;
537
    }
538

    
539
    /**
540
     * @return
541
     */
542
    public BulkEditorQuery getLastQuery() {
543
       return lastQuery;
544
    }
545

    
546
    /**
547
     * @param object
548
     */
549
    public void setLastQuery(BulkEditorQuery lastQuery) {
550
       this.lastQuery = lastQuery;
551

    
552
    }
553

    
554
    /**
555
     * {@inheritDoc}
556
     */
557
    @Override
558
    public Taxon getTaxon() {
559
        ISelection selection = viewer.getSelection();
560
        if(selection instanceof IStructuredSelection
561
                && ((IStructuredSelection) selection).size()==1) {
562
            Object object = ((IStructuredSelection) selection).iterator().next();
563
            if(object instanceof Taxon){
564
                return (Taxon) object;
565
            }
566
        }
567
        return null;
568
    }
569

    
570
}
(1-1/5)