improve deduplication handling and saving in bulkeditor
[taxeditor.git] / eu.etaxonomy.taxeditor.bulkeditor / src / main / java / eu / etaxonomy / taxeditor / bulkeditor / e4 / BulkEditorE4.java
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.viewers.ArrayContentProvider;
30 import org.eclipse.jface.viewers.CellEditor;
31 import org.eclipse.jface.viewers.ColumnViewerEditor;
32 import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
33 import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
34 import org.eclipse.jface.viewers.ICellModifier;
35 import org.eclipse.jface.viewers.ISelection;
36 import org.eclipse.jface.viewers.ISelectionChangedListener;
37 import org.eclipse.jface.viewers.IStructuredSelection;
38 import org.eclipse.jface.viewers.ITableLabelProvider;
39 import org.eclipse.jface.viewers.TableViewer;
40 import org.eclipse.jface.viewers.TableViewerColumn;
41 import org.eclipse.jface.viewers.TableViewerEditor;
42 import org.eclipse.jface.viewers.TableViewerFocusCellManager;
43 import org.eclipse.jface.viewers.TextCellEditor;
44 import org.eclipse.swt.SWT;
45 import org.eclipse.swt.events.MouseEvent;
46 import org.eclipse.swt.layout.FillLayout;
47 import org.eclipse.swt.layout.GridData;
48 import org.eclipse.swt.layout.GridLayout;
49 import org.eclipse.swt.widgets.Composite;
50 import org.eclipse.swt.widgets.Table;
51
52 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
53 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
54 import eu.etaxonomy.cdm.model.common.CdmBase;
55 import eu.etaxonomy.cdm.model.taxon.Taxon;
56 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
57 import eu.etaxonomy.taxeditor.bulkeditor.BulkEditorQuery;
58 import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
59 import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
60 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
61 import eu.etaxonomy.taxeditor.l10n.Messages;
62 import eu.etaxonomy.taxeditor.model.AbstractUtility;
63 import eu.etaxonomy.taxeditor.model.IDerivedUnitFacadePart;
64 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
65 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
66 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
67 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
68 import eu.etaxonomy.taxeditor.model.IPartContentHasSupplementalData;
69 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
70 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
71
72 /**
73 *
74 * @author pplitzner
75 * @since Sep 8, 2017
76 *
77 */
78 public class BulkEditorE4 implements IPartContentHasDetails, IConversationEnabled, IPostOperationEnabled,
79 IDirtyMarkable, IDerivedUnitFacadePart, IPartContentHasFactualData,
80 IPartContentHasSupplementalData, IPartContentHasMedia, IE4SavablePart, ITaxonEditor {
81
82 @Inject
83 private MDirtyable dirty;
84
85 private AbstractBulkEditorInput<?> input;
86
87 private Composite topComposite;
88
89 private TableViewer viewer;
90
91 private ConversationHolder conversation;
92
93 @Inject
94 private ESelectionService selService;
95
96 @Inject
97 private IEventBroker eventBroker;
98
99 private ISelectionChangedListener selectionChangedListener;
100
101 @Inject
102 private MPart thisPart;
103
104 private BulkEditorQuery lastQuery = null;
105
106 @Inject
107 public BulkEditorE4() {
108 }
109
110 public void init(AbstractBulkEditorInput<?> input){
111 this.input = input;
112 this.conversation = input.getConversation();
113
114 BulkEditorSearchE4 searchBar = new BulkEditorSearchE4(this, topComposite, SWT.NONE);
115 //layout needed because the search bar is added after @PostConstuct method
116 topComposite.getParent().layout();
117
118 thisPart.setLabel(input.getName());
119
120 //create columns
121 Table table = viewer.getTable();
122 String[] titles = {input.getName(), "Type"};
123 int[] bounds = {500, 100};
124
125 ColumnViewerEditorActivationStrategy activationSupport = new ColumnViewerEditorActivationStrategy(viewer) {
126 @Override
127 protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
128 // Enable editor only with mouse double click
129 if (event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION) {
130 EventObject source = event.sourceEvent;
131 if (source instanceof MouseEvent && ((MouseEvent)source).button == 3) {
132 return false;
133 }
134
135 return true;
136 }
137
138 return false;
139 }
140 };
141 TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(viewer, new BulkEditorFocusCellOwnerDrawHighLighter(viewer));
142
143 TableViewerEditor.create(viewer, focusCellManager, activationSupport, ColumnViewerEditor.TABBING_HORIZONTAL |
144 ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR |
145 ColumnViewerEditor.TABBING_VERTICAL |
146 ColumnViewerEditor.KEYBOARD_ACTIVATION );
147
148 CellEditor[] editors = new CellEditor[titles.length];
149 for (int i = 0; i < titles.length; i++) {
150 TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
151 editors[i] = new TextCellEditor(table);
152
153 column.getColumn().setText(titles[i]);
154 column.getColumn().setWidth(bounds[i]);
155 column.getColumn().setResizable(true);
156 column.getColumn().setMoveable(true);
157
158 }
159
160 table.setHeaderVisible(true);
161 table.setLinesVisible(true);
162
163 viewer.setCellEditors(editors);
164 viewer.setColumnProperties(titles);
165
166 //content and label provider (NOTE: has to be set AFTER creating cell editors
167 viewer.setContentProvider(new ArrayContentProvider());
168 BulkEditorLabelProvider labelProvider = new BulkEditorLabelProvider(this);
169 viewer.setLabelProvider(labelProvider);
170
171
172 //allow text selection
173 viewer.setCellModifier(new ICellModifier() {
174 @Override
175 public void modify(Object element, String property, Object value) {
176 }
177 @Override
178 public Object getValue(Object element, String property) {
179 ITableLabelProvider tableLabelProvider = null;
180 if(viewer.getLabelProvider() instanceof ITableLabelProvider){
181 tableLabelProvider = (ITableLabelProvider) viewer.getLabelProvider();
182 }
183 Object[] columnProperties = viewer.getColumnProperties();
184 for (int i=0;i<columnProperties.length;i++) {
185 if(columnProperties[i].equals(property) && tableLabelProvider!=null){
186 return tableLabelProvider.getColumnText(element, i);
187 }
188 }
189 return "";
190 }
191 @Override
192 public boolean canModify(Object element, String property) {
193 return true;
194 }
195 });
196
197
198
199 if(input.getEntityUuid()!=null){
200 performSearch(new BulkEditorQuery(input.getEntityUuid().toString(), null));
201 }
202 }
203
204 /** {@inheritDoc} */
205 @PostConstruct
206 public void createPartControl(Composite parent, EMenuService menuService) {
207 parent.setLayout(new GridLayout());
208
209 topComposite = new Composite(parent, SWT.NONE);
210 topComposite.setLayout(new GridLayout());
211
212 GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
213 topComposite.setLayoutData(gridData);
214
215 Composite bottomComposite = new Composite(parent, SWT.NONE);
216 bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
217 bottomComposite.setLayout(new FillLayout());
218 viewer = new TableViewer(bottomComposite, SWT.MULTI | SWT.FULL_SELECTION);
219
220 // createColumns(viewer);
221
222 //propagate selection
223 selectionChangedListener = (event -> selService.setSelection(AbstractUtility.getElementsFromSelectionChangedEvent(event)));
224 viewer.addSelectionChangedListener(selectionChangedListener);
225
226 //create context menu
227 menuService.registerContextMenu(viewer.getControl(), "eu.etaxonomy.taxeditor.bulkeditor.popupmenu.bulkeditor"); //$NON-NLS-1$
228
229 }
230
231 @Override
232 @Persist
233 public void save(IProgressMonitor monitor) {
234 save(monitor, true);
235 }
236
237 @Focus
238 public void setFocus() {
239 //make sure to bind again if maybe in another view the conversation was unbound
240 eventBroker.post(WorkbenchEventConstants.CURRENT_ACTIVE_EDITOR, this);
241 }
242
243 @PreDestroy
244 public void dispose() {
245 if(conversation!=null){
246 conversation.unregisterForDataStoreChanges(this);
247 conversation.close();
248 }
249 if(input!=null){
250 input.dispose();
251 }
252 }
253
254 public void save(IProgressMonitor monitor, boolean resetMerge) {
255 if (!input.getCdmEntitySession().isActive()){
256 input.getCdmEntitySession().bind();
257 }
258 input.saveModel(resetMerge);
259
260 List<CdmBase> saveCandidates = getEditorInput().getSaveCandidates();
261
262
263 dirty.setDirty(false);
264 getEditorInput().resetSaveCandidates();
265 getEditorInput().dispose();
266 getEditorInput().bind();
267 conversation.commit(true);
268
269 if (lastQuery != null){
270 performSearch(lastQuery);
271 }
272 viewer.refresh();
273
274
275 }
276
277 /** {@inheritDoc} */
278 public void performSearch(BulkEditorQuery query) {
279 if (query != null) {
280
281 // TODO check if dirty, prompt save
282 if (isDirty()) {
283 String[] labels = {Messages.BulkEditorE4_SAVE_AND_SEARCH, Messages.BulkEditorE4_DONT_SAVE,Messages.BulkEditorE4_CANCEL};
284 MessageDialog dialog =new MessageDialog(topComposite.getShell(), Messages.BulkEditorE4_SAVE_CHANGES_TITLE, null, Messages.BulkEditorE4_SAVE_CHANGES_MESSAGE, MessageDialog.QUESTION,labels, 0);
285 int result = dialog.open();
286 if (result == 0) {
287 save(new NullProgressMonitor());
288 } else if (result == 2){
289 return;
290 }
291 }
292 dirty.setDirty(false);
293 // getEditorInput().dispose();
294 // getEditorInput().bind();
295 getEditorInput().performSearch(query);
296 lastQuery = query;
297 viewer.setInput(getEditorInput().getModel());
298 refresh();
299 }
300 }
301
302 public void refresh() {
303 refresh(true);
304 }
305
306 public void refresh(boolean resetInput) {
307 if(resetInput){
308 viewer.setInput(getEditorInput().getModel());
309 }
310 viewer.refresh();
311 }
312
313 public TableViewer getViewer() {
314 return viewer;
315 }
316
317 public void setDirty(){
318 dirty.setDirty(true);
319 }
320
321 public boolean isDirty() {
322 return dirty.isDirty();
323 }
324
325 public AbstractBulkEditorInput getEditorInput() {
326 return input;
327 }
328
329 /**
330 * {@inheritDoc}
331 */
332 @Override
333 public void update(CdmDataChangeMap arg0) {
334 }
335
336 /**
337 * {@inheritDoc}
338 */
339 @Override
340 public boolean canAttachMedia() {
341 return true;
342 }
343
344 /**
345 * {@inheritDoc}
346 */
347 @Override
348 public void changed(Object element) {
349 if (element instanceof CdmBase) {
350 getEditorInput().addSaveCandidate((CdmBase)element);
351 }
352 dirty.setDirty(true);
353 }
354
355 /**
356 * {@inheritDoc}
357 */
358 @Override
359 public void forceDirty() {
360 dirty.setDirty(true);
361 }
362
363 /**
364 * {@inheritDoc}
365 */
366 @Override
367 public boolean postOperation(CdmBase objectAffectedByOperation) {
368 return false;
369 }
370
371 /**
372 * {@inheritDoc}
373 */
374 @Override
375 public boolean onComplete() {
376 return false;
377 }
378
379 /**
380 * {@inheritDoc}
381 */
382 @Override
383 public ConversationHolder getConversationHolder() {
384 return conversation;
385 }
386
387 /**
388 * @return
389 */
390 public BulkEditorQuery getLastQuery() {
391 return lastQuery;
392 }
393
394 /**
395 * @param object
396 */
397 public void setLastQuery(BulkEditorQuery lastQuery) {
398 this.lastQuery = lastQuery;
399
400 }
401
402 /**
403 * {@inheritDoc}
404 */
405 @Override
406 public Taxon getTaxon() {
407 ISelection selection = viewer.getSelection();
408 if(selection instanceof IStructuredSelection
409 && ((IStructuredSelection) selection).size()==1) {
410 Object object = ((IStructuredSelection) selection).iterator().next();
411 if(object instanceof Taxon){
412 return (Taxon) object;
413 }
414 }
415 return null;
416 }
417
418 }