Revert "mend"
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / view / e4 / AbstractCdmEditorPartE4.java
1 /**
2 * Copyright (C) 2017 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 package eu.etaxonomy.taxeditor.view.e4;
10
11 import java.util.Set;
12
13 import javax.annotation.PreDestroy;
14 import javax.inject.Inject;
15 import javax.inject.Named;
16
17 import org.apache.log4j.Logger;
18 import org.eclipse.e4.core.contexts.IEclipseContext;
19 import org.eclipse.e4.core.di.annotations.Optional;
20 import org.eclipse.e4.ui.di.PersistState;
21 import org.eclipse.e4.ui.di.UISynchronize;
22 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
23 import org.eclipse.e4.ui.services.IServiceConstants;
24 import org.eclipse.e4.ui.workbench.modeling.EPartService;
25 import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
26 import org.eclipse.jface.viewers.ISelectionChangedListener;
27 import org.eclipse.jface.viewers.IStructuredSelection;
28 import org.eclipse.jface.viewers.StructuredSelection;
29 import org.eclipse.jface.viewers.Viewer;
30 import org.eclipse.swt.SWTException;
31
32 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
33 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
34 import eu.etaxonomy.cdm.api.service.ITermService;
35 import eu.etaxonomy.cdm.api.service.IVocabularyService;
36 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
37 import eu.etaxonomy.cdm.model.name.TaxonName;
38 import eu.etaxonomy.cdm.model.taxon.Taxon;
39 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
40 import eu.etaxonomy.cdm.persistence.dto.TermDto;
41 import eu.etaxonomy.cdm.persistence.dto.TermVocabularyDto;
42 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
43 import eu.etaxonomy.taxeditor.editor.ITaxonEditor;
44 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
45 import eu.etaxonomy.taxeditor.model.MessagingUtils;
46 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
47 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
48 import eu.etaxonomy.taxeditor.store.CdmStore;
49 import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
50 import eu.etaxonomy.taxeditor.view.e4.details.DetailsViewerE4;
51 import eu.etaxonomy.taxeditor.workbench.WorkbenchUtility;
52 import eu.etaxonomy.taxeditor.workbench.part.ISelectionElementEditingPart;
53
54 /**
55 * @author pplitzner
56 * @since Aug 10, 2017
57 *
58 */
59 public abstract class AbstractCdmEditorPartE4
60 implements IConversationEnabled, IDirtyMarkable, ISelectionElementEditingPart, IPostOperationEnabled{
61
62 private DelaySelection delaySelection = null;
63 /**
64 * This is the monitor for the DelaySelection runnable.
65 * If it is <code>true</code> then it is currently delaying a selection.
66 */
67 private boolean isInDelay;
68 private boolean isEnabled;
69 private static final Logger logger = Logger.getLogger(AbstractCdmEditorPartE4.class);
70
71 /**
72 * This class invokes internal_selectionChanged() in a separate thread.
73 * This allows an asynchronous and/or delayed handling of selection changes
74 */
75 private class DelaySelection implements Runnable{
76 private Object selection;
77 private MPart activePart;
78 private MPart thisPart;
79
80 public DelaySelection(Object selection, MPart activePart, MPart thisPart) {
81 super();
82 this.selection = selection;
83 this.activePart= activePart;
84 this.thisPart = thisPart;
85 }
86
87 @Override
88 public void run() {
89 try{
90 selectionChanged_internal(selection, activePart, thisPart);
91 }
92 finally{
93 isInDelay = false;
94 }
95 }
96
97 public synchronized void setSelection(Object selection) {
98 this.selection = selection;
99 }
100
101 public synchronized void setActivePart(MPart activePart) {
102 this.activePart = activePart;
103 }
104
105 public synchronized void setThisPart(MPart thisPart) {
106 this.thisPart = thisPart;
107 }
108
109 }
110
111 protected Viewer viewer;
112
113 protected MPart thisPart;
114
115 protected MPart selectionProvidingPart;
116
117 protected Object previousSelection;
118
119 protected ISelectionChangedListener selectionChangedListener;
120
121 public ISelectionChangedListener getSelectionChangedListener() {
122 return selectionChangedListener;
123 }
124
125 @Inject
126 protected ESelectionService selService;
127
128 @Inject
129 protected IEclipseContext context;
130
131 protected abstract void selectionChanged_internal(Object selection, MPart activePart, MPart thisPart);
132
133 @Inject
134 public void selectionChanged(
135 @Optional@Named(IServiceConstants.ACTIVE_SELECTION)Object selection,
136 @Optional@Named(IServiceConstants.ACTIVE_PART)MPart activePart,
137 MPart thisPart, UISynchronize sync, EPartService partService){
138 //multiple selections are not supported
139 if(activePart!=null
140 && thisPart!=null
141 && !activePart.equals(thisPart)
142 && selection instanceof IStructuredSelection
143 && ((IStructuredSelection) selection).size()>1){
144 showEmptyPage();
145 return;
146 }
147 // no active editor found
148 if(activePart==thisPart && WorkbenchUtility.getActiveEditorPart(partService)==null){
149 showEmptyPage();
150 return;
151 }
152 if (viewer != null && viewer.getControl()!= null && viewer.getInput() != null && !viewer.getControl().isDisposed()){
153 try{
154 viewer.getControl().setEnabled(true);
155 }catch(SWTException e){
156 logger.debug("Something went wrong for viewer.getControl().setEnabled(true) in " + this.getClass().getSimpleName(), e);
157 }
158
159 }
160
161 if((previousSelection!=null && selection!=null) && (activePart != null && selectionProvidingPart != null && activePart.equals(selectionProvidingPart)) &&
162 (previousSelection==selection
163 || previousSelection.equals(selection)
164 || new StructuredSelection(selection).equals(previousSelection))
165 ) {
166 return;
167 }
168 if(delaySelection==null){
169 delaySelection = new DelaySelection(selection, activePart, thisPart);
170 }
171 delaySelection.setSelection(selection);
172 delaySelection.setActivePart(activePart);
173 delaySelection.setThisPart(thisPart);
174 if(!isInDelay){
175 isInDelay = true;
176 sync.asyncExec(delaySelection);
177 previousSelection = selection;
178 }
179 }
180
181 /** {@inheritDoc} */
182 @Override
183 public void changed(Object object) {
184 if(selectionProvidingPart!=null){
185 Object part = selectionProvidingPart.getObject();
186 if(part instanceof IDirtyMarkable){
187 ((IDirtyMarkable) part).changed(object);
188 }
189 }
190 }
191
192 public Viewer getViewer() {
193 return viewer;
194 }
195
196 protected void showViewer(IStructuredSelection selection, MPart activePart, Viewer viewer){
197 if(viewer!=null && viewer.getControl()!=null && !viewer.getControl().isDisposed()){
198 Object element = selection.getFirstElement();
199 Object part = createPartObject(activePart);
200 viewer.getControl().setEnabled(true);
201 if(selection.getFirstElement()!=null){
202 if (element instanceof Taxon){
203 Taxon taxon = HibernateProxyHelper.deproxy(element, Taxon.class);
204 if (taxon.isMisapplication() || taxon.isProparteSynonym() || taxon.isInvalidDesignation()){
205
206 if(part instanceof ITaxonEditor){
207 Taxon accepted = ((ITaxonEditor) part).getTaxon();
208 Set<TaxonRelationship> rels = taxon.getTaxonRelations(accepted);
209
210 if (rels != null && rels.iterator().hasNext() && !taxon.equals(accepted)){
211 TaxonRelationship rel = rels.iterator().next();
212 if ((rel.getType().isMisappliedNameOrInvalidDesignation() || rel.getType().isAnySynonym()) && !rel.getFromTaxon().equals(((ITaxonEditor) part).getTaxon())){
213 viewer.setInput(rel);
214 selectionProvidingPart = activePart;
215 return;
216 }
217 }
218 }
219
220
221 }
222 }
223 //unwrap term DTOs
224 if(element instanceof TermDto){
225 element = CdmStore.getService(ITermService.class).load(((TermDto) element).getUuid());
226 }
227 else if(element instanceof TermVocabularyDto){
228 element = CdmStore.getService(IVocabularyService.class).load(((TermVocabularyDto) element).getUuid());
229 }
230
231 selectionProvidingPart = activePart;
232 if (viewer instanceof DetailsViewerE4){
233 ((DetailsViewerE4)viewer).setInput(element, part);
234 if (!selectionProvidingPart.getElementId().equals("eu.etaxonomy.taxeditor.editor.view.checklist.e4.DistributionEditorPart")){
235 ((DetailsViewerE4)viewer).setDetailsEnabled(true);
236 }
237
238 }
239
240 else{
241 if (activePart.getObject() instanceof DetailsPartE4 && element instanceof TaxonName){
242 selectionProvidingPart = ((DetailsPartE4)activePart.getObject()).getSelectionProvidingPart();
243 }
244 viewer.setInput(element);
245 }
246 }
247 }
248 }
249
250 protected Object createPartObject(MPart activePart) {
251 Object partObject = activePart;
252 Object wrappedPart = WorkbenchUtility.getE4WrappedPart(activePart);
253 if(wrappedPart!=null){
254 partObject = wrappedPart;
255 }
256 return partObject;
257 }
258
259 protected void showEmptyPage() {
260 if(viewer!=null && viewer.getControl()!=null && !viewer.getControl().isDisposed() ){
261 viewer.setInput(null);
262 try{
263 if (!viewer.getControl().isDisposed()){
264 viewer.getControl().setEnabled(false);
265 }
266 }catch(SWTException e){
267 if (PreferencesUtil.isShowUpWidgetIsDisposedMessages() && e.getMessage().equals("Widget is disposed")){
268 MessagingUtils.errorDialog("Widget is disposed",
269 null,
270 MessagingUtils.WIDGET_IS_DISPOSED_MESSAGE,
271 null,
272 e,
273 true);
274
275 }
276 }
277
278 }
279 reset();
280 if(thisPart!=null){
281 thisPart.setLabel(getViewName());
282 }
283 }
284
285 protected IStructuredSelection createSelection(Object selection) {
286 if(selection==null){
287 return null;
288 }
289 IStructuredSelection structuredSelection;
290 if(!(selection instanceof IStructuredSelection)){
291 structuredSelection = new StructuredSelection(selection);
292 }
293 else{
294 structuredSelection = (IStructuredSelection) selection;
295 }
296 return structuredSelection;
297 }
298
299 /**
300 * {@inheritDoc}
301 */
302 @Override
303 public ConversationHolder getConversationHolder() {
304 if(selectionProvidingPart != null && selectionProvidingPart instanceof IConversationEnabled) {
305 return ((IConversationEnabled) selectionProvidingPart).getConversationHolder();
306 }
307 return null;
308 }
309
310 /**
311 * {@inheritDoc}
312 */
313 @Override
314 public boolean postOperation(Object objectAffectedByOperation) {
315 changed(objectAffectedByOperation);
316 return true;
317 }
318
319 /**
320 * {@inheritDoc}
321 */
322 @Override
323 public boolean onComplete() {
324 viewer.refresh();
325 return true;
326 }
327
328 /**
329 * {@inheritDoc}
330 */
331 @Override
332 public MPart getSelectionProvidingPart() {
333 return selectionProvidingPart;
334 }
335
336 @PreDestroy
337 private void dispose() {
338 }
339
340 private void reset(){
341 previousSelection = null;
342 selectionProvidingPart = null;
343 delaySelection = null;
344 context.deactivate();
345 }
346
347 @PersistState
348 private void persistState(){
349
350 }
351
352 /**
353 * {@inheritDoc}
354 */
355 @Override
356 public void update(CdmDataChangeMap arg0) {
357 }
358
359 /**
360 * {@inheritDoc}
361 */
362 @Override
363 public void forceDirty() {
364 }
365
366 protected abstract String getViewName();
367
368 }