2 * Copyright (C) 2007 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.
10 package eu
.etaxonomy
.taxeditor
.editor
;
12 import java
.util
.ArrayList
;
13 import java
.util
.List
;
14 import java
.util
.UUID
;
16 import org
.eclipse
.core
.commands
.operations
.IUndoContext
;
17 import org
.eclipse
.core
.commands
.operations
.UndoContext
;
18 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
19 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
20 import org
.eclipse
.ui
.IEditorInput
;
21 import org
.eclipse
.ui
.IEditorPart
;
22 import org
.eclipse
.ui
.IEditorSite
;
23 import org
.eclipse
.ui
.PartInitException
;
24 import org
.eclipse
.ui
.forms
.editor
.FormEditor
;
26 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationState
;
27 import eu
.etaxonomy
.cdm
.api
.application
.CdmChangeEvent
;
28 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
29 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
30 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
31 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
32 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
33 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
34 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
35 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
36 import eu
.etaxonomy
.taxeditor
.editor
.internal
.TaxeditorEditorPlugin
;
37 import eu
.etaxonomy
.taxeditor
.editor
.name
.TaxonNameEditor
;
38 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AbstractGroupedContainer
;
39 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
40 import eu
.etaxonomy
.taxeditor
.model
.DataChangeBridge
;
41 import eu
.etaxonomy
.taxeditor
.model
.IDataChangeBehavior
;
42 import eu
.etaxonomy
.taxeditor
.model
.IDirtyMarkable
;
43 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasDetails
;
44 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasFactualData
;
45 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasMedia
;
46 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
47 import eu
.etaxonomy
.taxeditor
.operation
.IPostOperationEnabled
;
48 import eu
.etaxonomy
.taxeditor
.session
.ICdmEntitySession
;
49 import eu
.etaxonomy
.taxeditor
.session
.ICdmEntitySessionEnabled
;
53 * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs
54 * for "Descriptions", "Concepts", "Geography", etc.
61 public class MultiPageTaxonEditor
extends FormEditor
implements
62 IPartContentHasFactualData
, IConversationEnabled
, ICdmEntitySessionEnabled
, IPostOperationEnabled
,
63 IDirtyMarkable
, IPartContentHasDetails
, ISecuredEditor
, IPartContentHasMedia
{
65 /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
66 public static final String ID
= "eu.etaxonomy.taxeditor.editor.taxon";
68 private boolean dirty
;
70 private ICdmEntitySession cdmEntitySession
;
71 private ConversationHolder conversation
;
72 private IDataChangeBehavior dataChangeBehavior
;
73 private IUndoContext undoContext
;
75 private TaxonEditorInput input
;
79 * Constructor for MultiPageTaxonEditor.
82 public MultiPageTaxonEditor() {
84 undoContext
= new UndoContext();
90 public void dispose() {
91 if(cdmEntitySession
!= null) {
92 cdmEntitySession
.dispose();
94 conversation
.unregisterForDataStoreChanges(this);
102 * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
106 protected void addPages() {
107 input
= (TaxonEditorInput
) getEditorInput();
108 conversation
= input
.getConversationHolder();
109 conversation
.registerForDataStoreChanges(this);
110 CdmApplicationState
.getCurrentDataChangeService().register(this);
112 addPage(Page
.NAME
.getIndex(), new TaxonNameEditor(this),
114 // setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
117 // addPage(Page.DESCRIPTIVE.getIndex(), new
118 // TaxonDescriptionTreeEditor(this), getEditorInput());
119 // setPageText(Page.DESCRIPTIVE.getIndex(),
120 // Page.DESCRIPTIVE.getTitle());
122 // EditorUtil.showPropertySheet();
124 } catch (PartInitException e
) {
125 MessagingUtils
.error(getClass(), e
);
131 public void doSave(IProgressMonitor monitor
) {
132 monitor
.beginTask("Saving Editor", 4);
134 if (!conversation
.isBound()) {
139 for (IEditorPart editorPage
: getPages()) {
140 if (editorPage
instanceof TaxonNameEditor
) {
141 if (((TaxonNameEditor
) editorPage
).checkForEmptyNames()) {
142 MessageDialog
.openWarning(AbstractUtility
.getShell(), "No Name Specified",
143 "An attempt was made to save a taxon or synonym with "
144 + "an empty name. Operation was cancelled.");
149 editorPage
.doSave(monitor
);
153 // commit the conversation and start a new transaction immediately
156 conversation
.commit(true);
159 this.setDirty(false);
161 } catch (Exception e
) {
163 MessagingUtils
.operationDialog(this, e
, TaxeditorEditorPlugin
.PLUGIN_ID
,"saving a taxon", " Please close and reopen the taxon again.");
170 private void disableEditor(boolean isOnError
) {
171 for (IMultiPageTaxonEditorPage editorPage
: getPages()) {
173 editorPage
.setOnError();
175 editorPage
.setDisabled();
178 CdmApplicationState
.getCurrentDataChangeService().unregister(this);
179 conversation
.unregisterForDataStoreChanges(this);
180 conversation
.close();
184 private void setDirty(boolean dirty
) {
186 firePropertyChange(PROP_DIRTY
);
192 * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
202 public boolean isDirty() {
209 * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
213 public void editorDirtyStateChanged() {
215 super.editorDirtyStateChanged();
221 * Checks whether nested editors are calling
222 * <code>firePropertyChange(PROP_DIRTY)</code> to signal an edit has taken
223 * place before passing property change along to
224 * <code>super.handlePropertyChange(int propertyId)</code>.
229 * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
232 protected void handlePropertyChange(int propertyId
) {
233 if (propertyId
== PROP_DIRTY
) {
236 super.handlePropertyChange(propertyId
);
241 public void doSaveAs() {
246 public boolean isSaveAsAllowed() {
252 public void init(IEditorSite site
, IEditorInput input
)
253 throws PartInitException
{
255 if (!(input
instanceof TaxonEditorInput
)) {
256 throw new PartInitException(
257 "Invalid Input: Must be TaxonEditorInput");
260 this.input
= (TaxonEditorInput
) input
;
261 cdmEntitySession
= this.input
.getCdmEntitySession();
264 // // Listen for name changes,
265 // // change tab for this taxon editor accordingly
266 // getTaxon().addPropertyChangeListener("name",
267 // new PropertyChangeListener() {
268 // public void propertyChange(PropertyChangeEvent e) {
272 // } catch (NullPointerException e) {
273 // EditorUtil.warn(getClass(),
274 // "Caught an NPE while initing an editor. This is most " +
275 // "likely due to the unsuccesful attempt to restore the former " +
276 // "state of the application. We ignore this because the workbench " +
277 // "will simply be reset.");
281 super.init(site
, input
);
285 * Calls <code>MultiPageEditorPart.setPartName(String partName)</code> with
286 * text appropriate to the state of the taxon: any taxon that has been saved
287 * will by necessity have a name to display; a new taxon should display
288 * "New taxon" in the editor tab.
290 protected void setPartName() {
292 String partName
= null;
293 TaxonNameBase
<?
, ?
> name
= getTaxon().getName();
296 partName
= name
.getTitleCache();
299 if (partName
== null || partName
.equals("")) {
300 partName
= ("New taxon");
303 setPartName(partName
);
309 * Editor pages call this in their postOperation to notify the
310 * MultiPageTaxonEditor of unsaved changes
313 public void changed(Object element
) {
316 super.editorDirtyStateChanged();
317 if (element
instanceof TaxonBase
) {
318 TaxonNameEditor page
= (TaxonNameEditor
) getPage(Page
.NAME
);
319 AbstractGroupedContainer container
= page
.getContainer((TaxonBase
) element
);
320 if (container
!= null) {
325 //TODO: refresh taxon node in taxon navigator
330 * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
333 public void forceDirty() {
338 * The accepted taxon that is the input for this editor
340 * @return the accepted taxon
342 public Taxon
getTaxon() {
343 return input
.getTaxon();
350 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
355 * getConversationHolder
358 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
362 public ConversationHolder
getConversationHolder() {
368 * setConversationHolder
371 * @param conversation
372 * a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
375 public void setConversationHolder(ConversationHolder conversation
) {
376 this.conversation
= conversation
;
381 * Getter for the field <code>undoContext</code>.
384 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
387 public IUndoContext
getUndoContext() {
393 * Setter for the field <code>undoContext</code>.
397 * a {@link org.eclipse.core.commands.operations.IUndoContext}
400 public void setUndoContext(IUndoContext undoContext
) {
401 this.undoContext
= undoContext
;
406 public void setFocus() {
407 // logger.warn("Setting focus to editor");
408 // bind the conversation
409 getConversationHolder().bind();
410 if(cdmEntitySession
!= null) {
411 cdmEntitySession
.bind();
413 // pass focus to the active editor page
414 getActiveEditor().setFocus();
421 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
422 * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
426 public void update(CdmDataChangeMap events
) {
427 if (dataChangeBehavior
== null) {
428 dataChangeBehavior
= new MultiPageTaxonEditorDataChangeBehaviour(this);
431 DataChangeBridge
.handleDataChange(events
, dataChangeBehavior
);
438 * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
443 public boolean postOperation(CdmBase objectAffectedByOperation
) {
446 for (IEditorPart editor
: this.getPages()) {
447 if (editor
instanceof IPostOperationEnabled
) {
448 ((IPostOperationEnabled
) editor
).postOperation(objectAffectedByOperation
);
450 MessagingUtils
.warn(getClass(), "postOperation not enabled for editor " + editor
);
453 MessagingUtils
.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
459 * Returns an <code>IEditorPart</code> implementation by type
463 * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
466 public IMultiPageTaxonEditorPage
getPage(Page page
) {
467 for (IEditorPart editor
: this.getPages()) {
468 if (editor
.getClass().equals(page
.getClazz())) {
469 return (IMultiPageTaxonEditorPage
) editor
;
476 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
477 * <code>MultiPageTaxonEditor</code>.
479 * @return a {@link java.util.List} object.
481 public List
<IMultiPageTaxonEditorPage
> getPages() {
482 ArrayList
<IMultiPageTaxonEditorPage
> editors
= new ArrayList
<IMultiPageTaxonEditorPage
>();
483 for (int i
= 0; i
< this.getPageCount(); i
++) {
485 editors
.add((IMultiPageTaxonEditorPage
) this.getEditor(i
));
491 * Refreshes a certain page of the MultipageTaxonEditor
494 * a {@link eu.etaxonomy.taxeditor.editor.Page} object.
497 public boolean redraw(Page page
) {
498 return redraw(page
, true);
502 * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
506 * a {@link eu.etaxonomy.taxeditor.editor.Page} object.
511 public boolean redraw(Page page
, boolean focus
) {
512 IMultiPageTaxonEditorPage editorPage
= getPage(page
);
513 return editorPage
!= null && editorPage
.redraw(focus
);
524 public boolean onComplete() {
529 * Reloads the data for this
531 public void reload() {
533 MessagingUtils
.warningDialog("Editor has unsaved data", getClass(), "This editor can not be "
534 + "refreshed because it contains unsaved data. Refreshing "
535 + "this editor would discard the changes. Please save this editor, "
536 + "close and reopen it manually in order to get the latest content");
538 TaxonEditorInput input
= (TaxonEditorInput
) getEditorInput();
540 UUID uuid
= input
.getTaxonNode().getUuid();
542 conversation
.clear();
545 TaxonEditorInput newInput
= TaxonEditorInput
.NewInstance(uuid
);
547 for (IMultiPageTaxonEditorPage editorPart
: getPages()) {
550 } catch (Exception e
) {
551 MessagingUtils
.messageDialog("Error refreshing editor", getClass(), "Could not refresh this editor", e
);
557 public String
toString() {
558 return String
.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput());
562 public boolean permissionsSatisfied() {
563 IEditorPart activeEditor
= getActiveEditor();
564 if(activeEditor
!= null && ISecuredEditor
.class.isAssignableFrom(activeEditor
.getClass())){
565 return ((ISecuredEditor
)activeEditor
).permissionsSatisfied();
571 * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getCdmEntitySession()
574 public ICdmEntitySession
getCdmEntitySession() {
575 return cdmEntitySession
;
579 * @see eu.etaxonomy.taxeditor.session.ICdmEntitySessionEnabled#getRootEntities()
582 public List
<TaxonNode
> getRootEntities() {
583 return input
.getRootEntities();
587 * @see eu.etaxonomy.cdm.api.application.ICdmChangeListener#onChange(eu.etaxonomy.cdm.api.application.CdmChangeEvent)
590 public void onChange(CdmChangeEvent event
) {
591 // TODO Auto-generated method stub