Project

General

Profile

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

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

    
20
import org.eclipse.core.runtime.IProgressMonitor;
21
import org.eclipse.core.runtime.NullProgressMonitor;
22
import org.eclipse.e4.core.services.events.IEventBroker;
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.model.application.ui.basic.MPart;
27
import org.eclipse.e4.ui.services.EMenuService;
28
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
29
import org.eclipse.jface.dialogs.MessageDialog;
30
import org.eclipse.jface.layout.GridDataFactory;
31
import org.eclipse.jface.viewers.ISelection;
32
import org.eclipse.jface.viewers.ISelectionChangedListener;
33
import org.eclipse.jface.viewers.IStructuredSelection;
34
import org.eclipse.jface.viewers.TableViewer;
35
import org.eclipse.nebula.widgets.nattable.NatTable;
36
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
37
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
38
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
39
import org.eclipse.nebula.widgets.nattable.extension.glazedlists.GlazedListsEventLayer;
40
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
41
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
42
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
43
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
44
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
45
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
46
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
47
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
48
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
49
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
50
import org.eclipse.nebula.widgets.nattable.layer.stack.DefaultBodyLayerStack;
51
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
52
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
53
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
54
import org.eclipse.swt.SWT;
55
import org.eclipse.swt.layout.GridData;
56
import org.eclipse.swt.layout.GridLayout;
57
import org.eclipse.swt.widgets.Composite;
58

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

    
83
/**
84
 *
85
 * @author pplitzner
86
 * @since Sep 8, 2017
87
 *
88
 */
89
public class BulkEditorE4 implements IPartContentHasDetails, IConversationEnabled, IPostOperationEnabled,
90
        IDirtyMarkable, IDerivedUnitFacadePart, IPartContentHasFactualData,
91
        IPartContentHasSupplementalData, IPartContentHasMedia, IE4SavablePart, ITaxonEditor {
92

    
93
	@Inject
94
	private MDirtyable dirty;
95

    
96
    private AbstractBulkEditorInput<?> input;
97

    
98
    private Composite topComposite;
99

    
100
    private TableViewer viewer;
101

    
102
    private NatTable natTable;
103

    
104
    private ConversationHolder conversation;
105

    
106
    @Inject
107
    private ESelectionService selService;
108

    
109
    @Inject
110
    private IEventBroker eventBroker;
111

    
112
    private ISelectionChangedListener selectionChangedListener;
113

    
114
    @Inject
115
    private MPart thisPart;
116

    
117
    private BulkEditorQuery lastQuery = null;
118

    
119
    private BasicEventList<Object> list;
120

    
121
    @Inject
122
    public BulkEditorE4() {
123
	}
124

    
125
	@SuppressWarnings("unused")
126
    public void init(AbstractBulkEditorInput<?> input){
127
	    this.input = input;
128
	    this.conversation = input.getConversation();
129

    
130
	    new BulkEditorSearchE4(this, topComposite, SWT.NONE);
131
	    //layout needed because the search bar is added after @PostConstuct method
132
	    topComposite.getParent().layout();
133

    
134
	    thisPart.setLabel(input.getEditorName());
135

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

    
213

    
214

    
215
        if(input.getEntityUuid()!=null){
216
            performSearch(new BulkEditorQuery(input.getEntityUuid().toString(), null));
217
        }
218
	}
219

    
220
	/** {@inheritDoc} */
221
	@PostConstruct
222
	public void createPartControl(Composite parent, EMenuService menuService) {
223
		parent.setLayout(new GridLayout());
224

    
225
		topComposite = new Composite(parent, SWT.NONE);
226
		topComposite.setLayout(new GridLayout());
227

    
228
		GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
229
		topComposite.setLayoutData(gridData);
230

    
231
		Composite bottomComposite = new Composite(parent, SWT.NONE);
232
		bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
233
		bottomComposite.setLayout(new GridLayout());
234

    
235

    
236
		//++++NatTable++++
237
		natTable = createExampleControl(bottomComposite);
238
        GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
239

    
240

    
241

    
242

    
243

    
244

    
245

    
246

    
247

    
248

    
249

    
250

    
251

    
252
//		viewer = new TableViewer(bottomComposite, SWT.MULTI | SWT.FULL_SELECTION);
253

    
254
//		createColumns(viewer);
255

    
256
        //propagate selection
257
        selectionChangedListener = (event -> selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event)));
258
//        viewer.addSelectionChangedListener(selectionChangedListener);
259

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

    
263
	}
264
    private IDataProvider bodyDataProvider;
265
    private String[] propertyNames;
266
    private Map<String, String> propertyToLabels;
267

    
268
    public NatTable createExampleControl(Composite parent) {
269
        this.bodyDataProvider = setupBodyDataProvider();
270
        DefaultColumnHeaderDataProvider colHeaderDataProvider = new DefaultColumnHeaderDataProvider(
271
                this.propertyNames, this.propertyToLabels);
272
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(
273
                this.bodyDataProvider);
274

    
275
        DataLayer dataLayer = new DataLayer(bodyDataProvider);
276
        GlazedListsEventLayer eventLayer = new GlazedListsEventLayer<>(dataLayer, list);
277
        DefaultBodyLayerStack bodyLayer = new DefaultBodyLayerStack(eventLayer);
278

    
279
        ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(
280
                new DataLayer(colHeaderDataProvider),
281
                bodyLayer, bodyLayer.getSelectionLayer());
282

    
283
        RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(new DataLayer(rowHeaderDataProvider, 50, 20),
284
                bodyLayer, bodyLayer.getSelectionLayer());
285

    
286
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(
287
                colHeaderDataProvider, rowHeaderDataProvider);
288
        CornerLayer cornerLayer = new CornerLayer(new DataLayer(
289
                cornerDataProvider), rowHeaderLayer, columnHeaderLayer);
290

    
291
        GridLayer gridLayer = new GridLayer(bodyLayer, columnHeaderLayer,
292
                rowHeaderLayer, cornerLayer);
293
        NatTable natTable = new NatTable(parent, gridLayer);
294

    
295
        return natTable;
296
    }
297

    
298
    private IDataProvider setupBodyDataProvider() {
299
        list = new BasicEventList<>();
300

    
301
        this.propertyToLabels = new HashMap<>();
302
        this.propertyToLabels.put("titleCache", "Title Cache");
303
        this.propertyNames = new String[] { "titleCache" };
304
        return new ListDataProvider(list,
305
                new ReflectiveColumnPropertyAccessor(this.propertyNames));
306

    
307
    }
308

    
309
    public class BodyLayerStack extends AbstractLayerTransform {
310

    
311
        private SelectionLayer selectionLayer;
312

    
313
        public BodyLayerStack(IDataProvider dataProvider) {
314
            DataLayer bodyDataLayer = new DataLayer(dataProvider);
315
            ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(
316
                    bodyDataLayer);
317
            ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(
318
                    columnReorderLayer);
319
            this.selectionLayer = new SelectionLayer(columnHideShowLayer);
320
            ViewportLayer viewportLayer = new ViewportLayer(this.selectionLayer);
321
            setUnderlyingLayer(viewportLayer);
322
        }
323

    
324
        public SelectionLayer getSelectionLayer() {
325
            return this.selectionLayer;
326
        }
327
    }
328

    
329
	@Override
330
	@Persist
331
	public void save(IProgressMonitor monitor) {
332
	    save(monitor, true);
333
	}
334

    
335
	@Focus
336
	public void setFocus() {
337
	    //make sure to bind again if maybe in another view the conversation was unbound
338
	    eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, this);
339
	}
340

    
341
	@PreDestroy
342
	public void dispose() {
343
	    if(conversation!=null){
344
	        conversation.unregisterForDataStoreChanges(this);
345
	        conversation.close();
346
	    }
347
	    if(input!=null){
348
	        input.dispose();
349
	    }
350
	}
351

    
352
	public void save(IProgressMonitor monitor, boolean resetMerge) {
353
	    if (!input.getCdmEntitySession().isActive()){
354
            input.getCdmEntitySession().bind();
355
        }
356
	    input.saveModel(resetMerge);
357

    
358
	    List<CdmBase> saveCandidates = getEditorInput().getSaveCandidates();
359
	    ISelection selection = getViewer().getSelection();
360

    
361
        dirty.setDirty(false);
362
        getEditorInput().resetSaveCandidates();
363
        getEditorInput().dispose();
364
        getEditorInput().bind();
365
        conversation.commit(true);
366

    
367
        if (lastQuery != null){
368
            performSearch(lastQuery);
369
            getViewer().setSelection(selection, true);
370
        }
371
//        viewer.refresh();
372

    
373

    
374
	}
375

    
376
	/** {@inheritDoc} */
377
    public void performSearch(BulkEditorQuery query) {
378
        if (query != null) {
379

    
380
            // TODO check if dirty, prompt save
381
            if (isDirty()) {
382
                String[] labels = {Messages.BulkEditorE4_SAVE_AND_SEARCH, Messages.BulkEditorE4_DONT_SAVE,Messages.BulkEditorE4_CANCEL};
383
                MessageDialog dialog =new MessageDialog(topComposite.getShell(), Messages.BulkEditorE4_SAVE_CHANGES_TITLE, null, Messages.BulkEditorE4_SAVE_CHANGES_MESSAGE, MessageDialog.QUESTION,labels, 0);
384
                int result = dialog.open();
385
                if (result == 0) {
386
                    save(new NullProgressMonitor());
387
                } else if (result == 2){
388
                    return;
389
                }
390
            }
391
            dirty.setDirty(false);
392
//            getEditorInput().dispose();
393
//            getEditorInput().bind();
394
            getEditorInput().performSearch(query);
395
            lastQuery = query;
396
            List model = getEditorInput().getModel();
397
//            viewer.setInput(model);
398
            list.clear();
399
            list.addAll(model);
400

    
401
            refresh();
402
        }
403
    }
404

    
405
    public void refresh() {
406
        refresh(true);
407
    }
408

    
409
    public void refresh(boolean resetInput) {
410
        if(resetInput){
411
//            viewer.setInput(getEditorInput().getModel());
412
        }
413
//        viewer.refresh();
414
    }
415

    
416
    public TableViewer getViewer() {
417
        return viewer;
418
    }
419

    
420
    public void setDirty(){
421
        dirty.setDirty(true);
422
    }
423

    
424
    public boolean isDirty() {
425
        return dirty.isDirty();
426
    }
427

    
428
    public AbstractBulkEditorInput getEditorInput() {
429
        return input;
430
    }
431

    
432
    /**
433
     * {@inheritDoc}
434
     */
435
    @Override
436
    public void update(CdmDataChangeMap arg0) {
437
    }
438

    
439
    /**
440
     * {@inheritDoc}
441
     */
442
    @Override
443
    public boolean canAttachMedia() {
444
        return true;
445
    }
446

    
447
    /**
448
     * {@inheritDoc}
449
     */
450
    @Override
451
    public void changed(Object element) {
452
        if(element instanceof DerivedUnitFacade){
453
            DerivedUnit derivedUnit = ((DerivedUnitFacade) element).innerDerivedUnit();
454
            if(derivedUnit!=null){
455
                getEditorInput().addSaveCandidate(derivedUnit);
456
            }
457
            FieldUnit fieldUnit = ((DerivedUnitFacade) element).innerFieldUnit();
458
            if(fieldUnit!=null){
459
                getEditorInput().addSaveCandidate(fieldUnit);
460
            }
461
        }
462
        else if (element instanceof CdmBase) {
463
            getEditorInput().addSaveCandidate((CdmBase)element);
464
        }
465
        dirty.setDirty(true);
466
    }
467

    
468
    /**
469
     * {@inheritDoc}
470
     */
471
    @Override
472
    public void forceDirty() {
473
        dirty.setDirty(true);
474
    }
475

    
476
    /**
477
     * {@inheritDoc}
478
     */
479
    @Override
480
    public boolean postOperation(CdmBase objectAffectedByOperation) {
481
        return false;
482
    }
483

    
484
    /**
485
     * {@inheritDoc}
486
     */
487
    @Override
488
    public boolean onComplete() {
489
        return false;
490
    }
491

    
492
    /**
493
     * {@inheritDoc}
494
     */
495
    @Override
496
    public ConversationHolder getConversationHolder() {
497
        return conversation;
498
    }
499

    
500
    /**
501
     * @return
502
     */
503
    public BulkEditorQuery getLastQuery() {
504
       return lastQuery;
505
    }
506

    
507
    /**
508
     * @param object
509
     */
510
    public void setLastQuery(BulkEditorQuery lastQuery) {
511
       this.lastQuery = lastQuery;
512

    
513
    }
514

    
515
    /**
516
     * {@inheritDoc}
517
     */
518
    @Override
519
    public Taxon getTaxon() {
520
        ISelection selection = viewer.getSelection();
521
        if(selection instanceof IStructuredSelection
522
                && ((IStructuredSelection) selection).size()==1) {
523
            Object object = ((IStructuredSelection) selection).iterator().next();
524
            if(object instanceof Taxon){
525
                return (Taxon) object;
526
            }
527
        }
528
        return null;
529
    }
530

    
531
}
(1-1/4)