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
.application
.CdmChangeEvent
.Action
;
29 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
30 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
31 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
32 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
33 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
34 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
35 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
36 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
37 import eu
.etaxonomy
.taxeditor
.editor
.internal
.TaxeditorEditorPlugin
;
38 import eu
.etaxonomy
.taxeditor
.editor
.l10n
.Messages
;
39 import eu
.etaxonomy
.taxeditor
.editor
.name
.TaxonNameEditor
;
40 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AbstractGroupedContainer
;
41 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
42 import eu
.etaxonomy
.taxeditor
.model
.DataChangeBridge
;
43 import eu
.etaxonomy
.taxeditor
.model
.IDataChangeBehavior
;
44 import eu
.etaxonomy
.taxeditor
.model
.IDirtyMarkable
;
45 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasDetails
;
46 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasFactualData
;
47 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasMedia
;
48 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasSupplementalData
;
49 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
50 import eu
.etaxonomy
.taxeditor
.operation
.IPostOperationEnabled
;
54 * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs
55 * for "Descriptions", "Concepts", "Geography", etc.
62 public class MultiPageTaxonEditor
extends FormEditor
63 implements IPartContentHasFactualData
, IConversationEnabled
, IPostOperationEnabled
, IDirtyMarkable
,
64 IPartContentHasDetails
, IPartContentHasSupplementalData
, ISecuredEditor
, IPartContentHasMedia
, ITaxonEditor
{
66 /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
67 public static final String ID
= "eu.etaxonomy.taxeditor.editor.taxon"; //$NON-NLS-1$
69 private boolean dirty
;
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() {
92 conversation
.unregisterForDataStoreChanges(this);
100 * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
104 protected void addPages() {
105 input
= (TaxonEditorInput
) getEditorInput();
106 conversation
= input
.getConversationHolder();
107 conversation
.registerForDataStoreChanges(this);
110 addPage(Page
.NAME
.getIndex(), new TaxonNameEditor(this),
112 // setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
115 // addPage(Page.DESCRIPTIVE.getIndex(), new
116 // TaxonDescriptionTreeEditor(this), getEditorInput());
117 // setPageText(Page.DESCRIPTIVE.getIndex(),
118 // Page.DESCRIPTIVE.getTitle());
120 // EditorUtil.showPropertySheet();
122 } catch (PartInitException e
) {
123 MessagingUtils
.error(getClass(), e
);
131 protected void pageChange(int newPageIndex
) {
132 if(getCurrentPage()==-1){
135 super.pageChange(newPageIndex
);
140 public void doSave(IProgressMonitor monitor
) {
141 monitor
.beginTask(Messages
.MultiPageTaxonEditor_SAVING_EDITOR
, 4);
143 if (!conversation
.isBound()) {
148 for (IEditorPart editorPage
: getPages()) {
149 if (editorPage
instanceof TaxonNameEditor
) {
150 if (((TaxonNameEditor
) editorPage
).checkForEmptyNames()) {
151 MessageDialog
.openWarning(AbstractUtility
.getShell(), Messages
.MultiPageTaxonEditor_NO_NAME_SPECIFIED
,
152 Messages
.MultiPageTaxonEditor_NO_NAME_SPECIFIED_MESSAGE
);
157 editorPage
.doSave(monitor
);
161 // commit the conversation and start a new transaction immediately
165 conversation
.commit(true);
166 CdmApplicationState
.getCurrentDataChangeService()
167 .fireChangeEvent(new CdmChangeEvent(Action
.Update
, input
.getTaxonNode() , MultiPageTaxonEditor
.class), true);
170 this.setDirty(false);
172 } catch (Exception e
) {
174 MessagingUtils
.operationDialog(this, e
, TaxeditorEditorPlugin
.PLUGIN_ID
,Messages
.MultiPageTaxonEditor_SAVING_TAXON
, Messages
.MultiPageTaxonEditor_SAVING_TAXON_MESSAGE
);
181 private void disableEditor(boolean isOnError
) {
182 for (IMultiPageTaxonEditorPage editorPage
: getPages()) {
184 editorPage
.setOnError();
186 editorPage
.setDisabled();
190 conversation
.unregisterForDataStoreChanges(this);
191 conversation
.close();
195 private void setDirty(boolean dirty
) {
197 firePropertyChange(PROP_DIRTY
);
203 * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
213 public boolean isDirty() {
220 * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
224 public void editorDirtyStateChanged() {
226 super.editorDirtyStateChanged();
232 * Checks whether nested editors are calling
233 * <code>firePropertyChange(PROP_DIRTY)</code> to signal an edit has taken
234 * place before passing property change along to
235 * <code>super.handlePropertyChange(int propertyId)</code>.
240 * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
243 protected void handlePropertyChange(int propertyId
) {
244 if (propertyId
== PROP_DIRTY
) {
247 super.handlePropertyChange(propertyId
);
252 public void doSaveAs() {
257 public boolean isSaveAsAllowed() {
263 public void init(IEditorSite site
, IEditorInput input
)
264 throws PartInitException
{
266 if (!(input
instanceof TaxonEditorInput
)) {
267 throw new PartInitException(
268 Messages
.MultiPageTaxonEditor_INVALID_INPUT
);
271 this.input
= (TaxonEditorInput
) input
;
275 // // Listen for name changes,
276 // // change tab for this taxon editor accordingly
277 // getTaxon().addPropertyChangeListener("name",
278 // new PropertyChangeListener() {
279 // public void propertyChange(PropertyChangeEvent e) {
283 // } catch (NullPointerException e) {
284 // EditorUtil.warn(getClass(),
285 // "Caught an NPE while initing an editor. This is most " +
286 // "likely due to the unsuccesful attempt to restore the former " +
287 // "state of the application. We ignore this because the workbench " +
288 // "will simply be reset.");
292 super.init(site
, input
);
296 * Calls <code>MultiPageEditorPart.setPartName(String partName)</code> with
297 * text appropriate to the state of the taxon: any taxon that has been saved
298 * will by necessity have a name to display; a new taxon should display
299 * "New taxon" in the editor tab.
301 protected void setPartName() {
303 String partName
= null;
304 TaxonName name
= getTaxon().getName();
307 partName
= name
.getTitleCache();
310 if (partName
== null || partName
.equals("")) { //$NON-NLS-1$
311 partName
= (Messages
.MultiPageTaxonEditor_NEW_TAXON
);
314 setPartName(partName
);
320 * Editor pages call this in their postOperation to notify the
321 * MultiPageTaxonEditor of unsaved changes
324 public void changed(Object element
) {
326 // if the attribute is null then do not set the dirty flag -> hotfix for the problem that for tasks done in service methods the changes are saved automatically
327 if (element
!= null){
329 super.editorDirtyStateChanged();
332 if (element
instanceof TaxonBase
) {
333 TaxonNameEditor page
= (TaxonNameEditor
) getPage(Page
.NAME
);
334 AbstractGroupedContainer container
= page
.getContainer((TaxonBase
) element
);
335 if (container
!= null) {
339 if (element
instanceof TaxonRelationship
) {
340 TaxonNameEditor page
= (TaxonNameEditor
) getPage(Page
.NAME
);
341 AbstractGroupedContainer container
= page
.getContainer(((TaxonRelationship
) element
).getFromTaxon());
342 if (container
!= null) {
347 //TODO: refresh taxon node in taxon navigator
352 * @see eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider#forceDirty()
355 public void forceDirty() {
360 * The accepted taxon that is the input for this editor
362 * @return the accepted taxon
365 public Taxon
getTaxon() {
366 return input
.getTaxon();
373 * eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder
378 * getConversationHolder
381 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
385 public ConversationHolder
getConversationHolder() {
391 * setConversationHolder
394 * @param conversation
395 * a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
398 public void setConversationHolder(ConversationHolder conversation
) {
399 this.conversation
= conversation
;
404 * Getter for the field <code>undoContext</code>.
407 * @return a {@link org.eclipse.core.commands.operations.IUndoContext}
410 public IUndoContext
getUndoContext() {
416 * Setter for the field <code>undoContext</code>.
420 * a {@link org.eclipse.core.commands.operations.IUndoContext}
423 public void setUndoContext(IUndoContext undoContext
) {
424 this.undoContext
= undoContext
;
429 public void setFocus() {
430 // logger.warn("Setting focus to editor");
431 // bind the conversation
432 getConversationHolder().bind();
434 // pass focus to the active editor page
435 getActiveEditor().setFocus();
442 * eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu
443 * .etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
447 public void update(CdmDataChangeMap events
) {
448 if (dataChangeBehavior
== null) {
449 dataChangeBehavior
= new MultiPageTaxonEditorDataChangeBehaviour(this);
452 DataChangeBridge
.handleDataChange(events
, dataChangeBehavior
);
459 * eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation
464 public boolean postOperation(CdmBase objectAffectedByOperation
) {
467 for (IEditorPart editor
: this.getPages()) {
468 if (editor
instanceof IPostOperationEnabled
) {
469 ((IPostOperationEnabled
) editor
).postOperation(objectAffectedByOperation
);
471 MessagingUtils
.warn(getClass(), Messages
.MultiPageTaxonEditor_POST_OP_NOT_ENABLED
+ editor
);
474 MessagingUtils
.warn(getClass(), Messages
.MultiPageTaxonEditor_POST_OP_CALLED
);
480 * Returns an <code>IEditorPart</code> implementation by type
484 * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage}
487 public IMultiPageTaxonEditorPage
getPage(Page page
) {
488 for (IEditorPart editor
: this.getPages()) {
489 if (editor
.getClass().equals(page
.getClazz())) {
490 return (IMultiPageTaxonEditorPage
) editor
;
497 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
498 * <code>MultiPageTaxonEditor</code>.
500 * @return a {@link java.util.List} object.
502 public List
<IMultiPageTaxonEditorPage
> getPages() {
503 ArrayList
<IMultiPageTaxonEditorPage
> editors
= new ArrayList
<IMultiPageTaxonEditorPage
>();
504 for (int i
= 0; i
< this.getPageCount(); i
++) {
506 editors
.add((IMultiPageTaxonEditorPage
) this.getEditor(i
));
512 * Refreshes a certain page of the MultipageTaxonEditor
515 * a {@link eu.etaxonomy.taxeditor.editor.Page} object.
518 public boolean redraw(Page page
) {
519 return redraw(page
, true);
523 * Refreshes a certain page of the MultipageTaxonEditor and sets focus to
527 * a {@link eu.etaxonomy.taxeditor.editor.Page} object.
532 public boolean redraw(Page page
, boolean focus
) {
533 IMultiPageTaxonEditorPage editorPage
= getPage(page
);
534 return editorPage
!= null && editorPage
.redraw(focus
);
545 public boolean onComplete() {
550 * Reloads the data for this
552 public void reload() {
554 MessagingUtils
.warningDialog(Messages
.MultiPageTaxonEditor_UNSAVED_DATA
, getClass(), Messages
.MultiPageTaxonEditor_UNSAVED_DATA_MESSAGE
);
556 TaxonEditorInput input
= (TaxonEditorInput
) getEditorInput();
558 UUID uuid
= input
.getTaxonNode().getUuid();
560 conversation
.clear();
563 TaxonEditorInput newInput
= TaxonEditorInput
.NewInstance(uuid
);
565 for (IMultiPageTaxonEditorPage editorPart
: getPages()) {
568 } catch (Exception e
) {
569 MessagingUtils
.messageDialog(Messages
.MultiPageTaxonEditor_REFRESH_ERROR
, getClass(), Messages
.MultiPageTaxonEditor_REFRESH_ERROR_MESSAGE
, e
);
575 public String
toString() {
576 return String
.format("%s[%s]", this.getClass().getSimpleName(), getEditorInput()); //$NON-NLS-1$
580 public boolean permissionsSatisfied() {
581 IEditorPart activeEditor
= getActiveEditor();
582 if(activeEditor
!= null && ISecuredEditor
.class.isAssignableFrom(activeEditor
.getClass())){
583 return ((ISecuredEditor
)activeEditor
).permissionsSatisfied();
589 * @see eu.etaxonomy.taxeditor.model.IPartContentHasMedia#canAttachMedia()
592 public boolean canAttachMedia() {