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
.ui
.IEditorInput
;
20 import org
.eclipse
.ui
.IEditorPart
;
21 import org
.eclipse
.ui
.IEditorSite
;
22 import org
.eclipse
.ui
.PartInitException
;
23 import org
.eclipse
.ui
.forms
.editor
.FormEditor
;
25 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
26 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
27 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
28 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
29 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
30 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
31 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
32 import eu
.etaxonomy
.taxeditor
.editor
.name
.TaxonNameEditor
;
33 import eu
.etaxonomy
.taxeditor
.editor
.name
.container
.AbstractGroupedContainer
;
34 import eu
.etaxonomy
.taxeditor
.model
.DataChangeBridge
;
35 import eu
.etaxonomy
.taxeditor
.model
.IDataChangeBehavior
;
36 import eu
.etaxonomy
.taxeditor
.model
.IDirtyMarkableSelectionProvider
;
37 import eu
.etaxonomy
.taxeditor
.model
.IPartContentHasDetails
;
38 import eu
.etaxonomy
.taxeditor
.operation
.IPostOperationEnabled
;
42 * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs for
43 * "Descriptions", "Concepts", "Geography", etc.
50 public class MultiPageTaxonEditor
extends FormEditor
implements IConversationEnabled
, IPostOperationEnabled
, IDirtyMarkableSelectionProvider
, IPartContentHasDetails
{
52 /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.multipage"{trunked}</code> */
53 public static final String ID
= "eu.etaxonomy.taxeditor.editor.multipagetaxonview";
55 private boolean dirty
;
57 private ConversationHolder conversation
;
58 private IDataChangeBehavior dataChangeBehavior
;
59 private IUndoContext undoContext
;
61 private TaxonEditorInput input
;
64 * <p>Constructor for MultiPageTaxonEditor.</p>
66 public MultiPageTaxonEditor() {
68 undoContext
= new UndoContext();
73 public void dispose() {
74 conversation
.unregisterForDataStoreChanges(this);
80 * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
84 protected void addPages() {
85 input
= (TaxonEditorInput
) getEditorInput();
86 conversation
= input
.getConversationHolder();
87 conversation
.registerForDataStoreChanges(this);
90 addPage(Page
.NAME
.getIndex(), new TaxonNameEditor(this), getEditorInput());
91 // setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
94 // addPage(Page.DESCRIPTIVE.getIndex(), new TaxonDescriptionTreeEditor(this), getEditorInput());
95 // setPageText(Page.DESCRIPTIVE.getIndex(), Page.DESCRIPTIVE.getTitle());
97 // EditorUtil.showPropertySheet();
99 } catch (PartInitException e
) {
100 EditorUtil
.error(getClass(), e
);
107 public void doSave(IProgressMonitor monitor
) {
108 monitor
.beginTask("Saving Editor", 4);
110 if( ! conversation
.isBound()){
115 for(IEditorPart editorPage
: getPages()){
116 if(editorPage
instanceof TaxonNameEditor
){
117 if(((TaxonNameEditor
) editorPage
).checkForEmptyNames()){
123 editorPage
.doSave(monitor
);
127 // commit the conversation and start a new transaction immediately
128 conversation
.commit(true);
131 this.setDirty(false);
139 private void setDirty(boolean dirty
) {
141 firePropertyChange(PROP_DIRTY
);
145 * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
152 public boolean isDirty() {
157 * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
161 public void editorDirtyStateChanged() {
163 super.editorDirtyStateChanged();
170 * Checks whether nested editors are calling <code>firePropertyChange(PROP_DIRTY)</code>
171 * to signal an edit has taken place before passing property change along to
172 * <code>super.handlePropertyChange(int propertyId)</code>.
175 * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
177 protected void handlePropertyChange(int propertyId
) {
178 if (propertyId
== PROP_DIRTY
) {
181 super.handlePropertyChange(propertyId
);
186 public void doSaveAs() {}
190 public boolean isSaveAsAllowed() {
196 public void init(IEditorSite site
, IEditorInput input
) throws PartInitException
{
198 if (!(input
instanceof TaxonEditorInput
))
199 throw new PartInitException(
200 "Invalid Input: Must be TaxonEditorInput");
202 this.input
= (TaxonEditorInput
) input
;
205 // // Listen for name changes,
206 // // change tab for this taxon editor accordingly
207 // getTaxon().addPropertyChangeListener("name",
208 // new PropertyChangeListener() {
209 // public void propertyChange(PropertyChangeEvent e) {
213 // } catch (NullPointerException e) {
214 // EditorUtil.warn(getClass(), "Caught an NPE while initing an editor. This is most " +
215 // "likely due to the unsuccesful attempt to restore the former " +
216 // "state of the application. We ignore this because the workbench " +
217 // "will simply be reset.");
221 super.init(site
, input
);
225 * Calls <code>MultiPageEditorPart.setPartName(String partName)</code>
226 * with text appropriate to the state of the taxon: any taxon that has
227 * been saved will by necessity have a name to display; a new taxon
228 * should display "New taxon" in the editor tab.
230 protected void setPartName() {
232 String partName
= null;
233 TaxonNameBase
<?
, ?
> name
= getTaxon().getName();
236 partName
= name
.getTitleCache();
239 if (partName
== null || partName
.equals("")) {
240 partName
= ("New taxon");
243 setPartName(partName
);
249 * Editor pages call this in their postOperation to notify the MultiPageTaxonEditor
252 public void changed(Object element
) {
255 super.editorDirtyStateChanged();
256 if(element
instanceof TaxonBase
){
257 TaxonNameEditor page
= (TaxonNameEditor
) getPage(Page
.NAME
);
258 AbstractGroupedContainer container
= page
.getContainer((TaxonBase
) element
);
259 if(container
!= null){
266 * The accepted taxon that is the input for this editor
268 * @return the accepted taxon
270 public Taxon
getTaxon(){
271 return input
.getTaxon();
276 * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
279 * <p>getConversationHolder</p>
281 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
283 public ConversationHolder
getConversationHolder() {
288 * <p>setConversationHolder</p>
290 * @param conversation a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
292 public void setConversationHolder(ConversationHolder conversation
){
293 this.conversation
= conversation
;
298 * <p>Getter for the field <code>undoContext</code>.</p>
300 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
302 public IUndoContext
getUndoContext() {
307 * <p>Setter for the field <code>undoContext</code>.</p>
309 * @param undoContext a {@link org.eclipse.core.commands.operations.IUndoContext} object.
311 public void setUndoContext(IUndoContext undoContext
) {
312 this.undoContext
= undoContext
;
317 public void setFocus(){
318 //logger.warn("Setting focus to editor");
319 // bind the conversation
320 getConversationHolder().bind();
321 // pass focus to the active editor page
322 getActiveEditor().setFocus();
327 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
330 public void update(CdmDataChangeMap events
) {
331 if(dataChangeBehavior
== null){
332 dataChangeBehavior
= new MultiPageTaxonEditorDataChangeBehaviour(this);
335 DataChangeBridge
.handleDataChange(events
, dataChangeBehavior
);
341 * @see eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation()
344 public boolean postOperation(CdmBase objectAffectedByOperation
) {
347 for(IEditorPart editor
: this.getPages()){
348 if (editor
instanceof IPostOperationEnabled
) {
349 ((IPostOperationEnabled
) editor
).postOperation(objectAffectedByOperation
);
351 EditorUtil
.warn(getClass(), "postOperation not enabled for editor " + editor
);
354 EditorUtil
.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
360 * Returns an <code>IEditorPart</code> implementation by type
362 * @param page the page type
363 * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage} object.
365 public IMultiPageTaxonEditorPage
getPage(Page page
){
366 for(IEditorPart editor
: this.getPages()){
367 if(editor
.getClass().equals(page
.getClazz())){
368 return (IMultiPageTaxonEditorPage
) editor
;
375 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
376 * <code>MultiPageTaxonEditor</code>.
378 * @return a {@link java.util.List} object.
380 public List
<IMultiPageTaxonEditorPage
> getPages(){
381 ArrayList
<IMultiPageTaxonEditorPage
> editors
= new ArrayList
<IMultiPageTaxonEditorPage
>();
382 for(int i
= 0; i
< this.getPageCount(); i
++){
384 editors
.add((IMultiPageTaxonEditorPage
) this.getEditor(i
));
390 * Refreshes a certain page of the MultipageTaxonEditor
392 * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
395 public boolean redraw(Page page
){
396 return redraw(page
, true);
400 * Refreshes a certain page of the MultipageTaxonEditor and
401 * sets focus to that page
403 * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
404 * @param focus a boolean.
407 public boolean redraw(Page page
, boolean focus
){
408 IMultiPageTaxonEditorPage editorPage
= getPage(page
);
409 return editorPage
!= null && editorPage
.redraw(focus
);
417 public boolean onComplete() {
422 * Reloads the data for this
424 public void reload() {
426 EditorUtil
.warningDialog("Editor has unsaved data", getClass(), "This editor can not be " +
427 "refreshed because it contains unsaved data. Refreshing " +
428 "this editor would discard the changes. Please save this editor, " +
429 "close and reopen it manually in order to get the latest content");
431 TaxonEditorInput input
= (TaxonEditorInput
) getEditorInput();
433 UUID uuid
= input
.getTaxonNode().getUuid();
435 conversation
.clear();
438 TaxonEditorInput newInput
= TaxonEditorInput
.NewInstance(uuid
);
440 for(IMultiPageTaxonEditorPage editorPart
: getPages()){
443 } catch (Exception e
) {
444 EditorUtil
.errorDialog("Error refreshing editor", getClass(), "Could not refresh this editor", e
);