2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.taxeditor
.view
.e4
;
13 import javax
.annotation
.PreDestroy
;
14 import javax
.inject
.Inject
;
15 import javax
.inject
.Named
;
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
;
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
;
59 public abstract class AbstractCdmEditorPartE4
60 implements IConversationEnabled
, IDirtyMarkable
, ISelectionElementEditingPart
, IPostOperationEnabled
{
62 private DelaySelection delaySelection
= null;
64 * This is the monitor for the DelaySelection runnable.
65 * If it is <code>true</code> then it is currently delaying a selection.
67 private boolean isInDelay
;
68 private boolean isEnabled
;
69 private static final Logger logger
= Logger
.getLogger(AbstractCdmEditorPartE4
.class);
72 * This class invokes internal_selectionChanged() in a separate thread.
73 * This allows an asynchronous and/or delayed handling of selection changes
75 private class DelaySelection
implements Runnable
{
76 private Object selection
;
77 private MPart activePart
;
78 private MPart thisPart
;
80 public DelaySelection(Object selection
, MPart activePart
, MPart thisPart
) {
82 this.selection
= selection
;
83 this.activePart
= activePart
;
84 this.thisPart
= thisPart
;
90 selectionChanged_internal(selection
, activePart
, thisPart
);
97 public synchronized void setSelection(Object selection
) {
98 this.selection
= selection
;
101 public synchronized void setActivePart(MPart activePart
) {
102 this.activePart
= activePart
;
105 public synchronized void setThisPart(MPart thisPart
) {
106 this.thisPart
= thisPart
;
111 protected Viewer viewer
;
113 protected MPart thisPart
;
115 protected MPart selectionProvidingPart
;
117 protected Object previousSelection
;
119 protected ISelectionChangedListener selectionChangedListener
;
121 public ISelectionChangedListener
getSelectionChangedListener() {
122 return selectionChangedListener
;
126 protected ESelectionService selService
;
129 protected IEclipseContext context
;
131 protected abstract void selectionChanged_internal(Object selection
, MPart activePart
, MPart thisPart
);
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
141 && !activePart
.equals(thisPart
)
142 && selection
instanceof IStructuredSelection
143 && ((IStructuredSelection
) selection
).size()>1){
147 // no active editor found
148 if(activePart
==thisPart
&& WorkbenchUtility
.getActiveEditorPart(partService
)==null){
152 if (viewer
!= null && viewer
.getControl()!= null && viewer
.getInput() != null && !viewer
.getControl().isDisposed()){
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
);
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
))
168 if(delaySelection
==null){
169 delaySelection
= new DelaySelection(selection
, activePart
, thisPart
);
171 delaySelection
.setSelection(selection
);
172 delaySelection
.setActivePart(activePart
);
173 delaySelection
.setThisPart(thisPart
);
176 sync
.asyncExec(delaySelection
);
177 previousSelection
= selection
;
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
);
192 public Viewer
getViewer() {
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()){
206 if(part
instanceof ITaxonEditor
){
207 Taxon accepted
= ((ITaxonEditor
) part
).getTaxon();
208 Set
<TaxonRelationship
> rels
= taxon
.getTaxonRelations(accepted
);
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
;
224 if(element
instanceof TermDto
){
225 element
= CdmStore
.getService(ITermService
.class).load(((TermDto
) element
).getUuid());
227 else if(element
instanceof TermVocabularyDto
){
228 element
= CdmStore
.getService(IVocabularyService
.class).load(((TermVocabularyDto
) element
).getUuid());
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);
241 if (activePart
.getObject() instanceof DetailsPartE4
&& element
instanceof TaxonName
){
242 selectionProvidingPart
= ((DetailsPartE4
)activePart
.getObject()).getSelectionProvidingPart();
244 viewer
.setInput(element
);
250 protected Object
createPartObject(MPart activePart
) {
251 Object partObject
= activePart
;
252 Object wrappedPart
= WorkbenchUtility
.getE4WrappedPart(activePart
);
253 if(wrappedPart
!=null){
254 partObject
= wrappedPart
;
259 protected void showEmptyPage() {
260 if(viewer
!=null && viewer
.getControl()!=null && !viewer
.getControl().isDisposed() ){
261 viewer
.setInput(null);
263 if (!viewer
.getControl().isDisposed()){
264 viewer
.getControl().setEnabled(false);
266 }catch(SWTException e
){
267 if (PreferencesUtil
.isShowUpWidgetIsDisposedMessages() && e
.getMessage().equals("Widget is disposed")){
268 MessagingUtils
.errorDialog("Widget is disposed",
270 MessagingUtils
.WIDGET_IS_DISPOSED_MESSAGE
,
281 thisPart
.setLabel(getViewName());
285 protected IStructuredSelection
createSelection(Object selection
) {
289 IStructuredSelection structuredSelection
;
290 if(!(selection
instanceof IStructuredSelection
)){
291 structuredSelection
= new StructuredSelection(selection
);
294 structuredSelection
= (IStructuredSelection
) selection
;
296 return structuredSelection
;
303 public ConversationHolder
getConversationHolder() {
304 if(selectionProvidingPart
!= null && selectionProvidingPart
instanceof IConversationEnabled
) {
305 return ((IConversationEnabled
) selectionProvidingPart
).getConversationHolder();
314 public boolean postOperation(Object objectAffectedByOperation
) {
315 changed(objectAffectedByOperation
);
323 public boolean onComplete() {
332 public MPart
getSelectionProvidingPart() {
333 return selectionProvidingPart
;
337 private void dispose() {
340 private void reset(){
341 previousSelection
= null;
342 selectionProvidingPart
= null;
343 delaySelection
= null;
344 context
.deactivate();
348 private void persistState(){
356 public void update(CdmDataChangeMap arg0
) {
363 public void forceDirty() {
366 protected abstract String
getViewName();