had to rename the packages to make them compliant with buckminster
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / MultiPageTaxonEditor.java
1 /**
2 * Copyright (C) 2007 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
10 package eu.etaxonomy.taxeditor.editor;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.UUID;
15
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;
25
26 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
27 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
28 import eu.etaxonomy.cdm.model.common.CdmBase;
29 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
30 import eu.etaxonomy.cdm.model.taxon.Taxon;
31 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
32 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
33 import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
34 import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
35 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
36 import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
37 import eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider;
38 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
39 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
40
41 /**
42 *
43 * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs for
44 * "Descriptions", "Concepts", "Geography", etc.
45 *
46 * @author p.ciardelli
47 * @author n.hoffmann
48 * @created 15.05.2008
49 * @version 1.0
50 */
51 public class MultiPageTaxonEditor extends FormEditor implements IConversationEnabled, IPostOperationEnabled, IDirtyMarkableSelectionProvider, IPartContentHasDetails {
52
53 /** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
54 public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon";
55
56 private boolean dirty;
57
58 private ConversationHolder conversation;
59 private IDataChangeBehavior dataChangeBehavior;
60 private IUndoContext undoContext;
61
62 private TaxonEditorInput input;
63
64 /**
65 * <p>Constructor for MultiPageTaxonEditor.</p>
66 */
67 public MultiPageTaxonEditor() {
68 super();
69 undoContext = new UndoContext();
70 }
71
72 /** {@inheritDoc} */
73 @Override
74 public void dispose() {
75 conversation.unregisterForDataStoreChanges(this);
76 conversation.close();
77 super.dispose();
78 }
79
80 /* (non-Javadoc)
81 * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
82 */
83 /** {@inheritDoc} */
84 @Override
85 protected void addPages() {
86 input = (TaxonEditorInput) getEditorInput();
87 conversation = input.getConversationHolder();
88 conversation.registerForDataStoreChanges(this);
89
90 try {
91 addPage(Page.NAME.getIndex(), new TaxonNameEditor(this), getEditorInput());
92 // setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
93
94 // TODO lazy create
95 // addPage(Page.DESCRIPTIVE.getIndex(), new TaxonDescriptionTreeEditor(this), getEditorInput());
96 // setPageText(Page.DESCRIPTIVE.getIndex(), Page.DESCRIPTIVE.getTitle());
97
98 // EditorUtil.showPropertySheet();
99
100 } catch (PartInitException e) {
101 EditorUtil.error(getClass(), e);
102 }
103 }
104
105
106 /** {@inheritDoc} */
107 @Override
108 public void doSave(IProgressMonitor monitor) {
109 monitor.beginTask("Saving Editor", 4);
110 try{
111 if( ! conversation.isBound()){
112 conversation.bind();
113 }
114 monitor.worked(1);
115
116 for(IEditorPart editorPage : getPages()){
117 if(editorPage instanceof TaxonNameEditor){
118 if(((TaxonNameEditor) editorPage).checkForEmptyNames()){
119 MessageDialog.openWarning(EditorUtil.getShell(), "No Name Specified", "An attempt was made to save a taxon or synonym with " +
120 "an empty name. Operation was cancelled.");
121 return;
122 }
123 }
124
125 editorPage.doSave(monitor);
126 monitor.worked(1);
127 }
128
129 // commit the conversation and start a new transaction immediately
130 conversation.commit(true);
131 monitor.worked(1);
132
133 this.setDirty(false);
134 monitor.worked(1);
135 }finally{
136 monitor.done();
137 }
138 }
139
140
141 private void setDirty(boolean dirty) {
142 this.dirty = dirty;
143 firePropertyChange(PROP_DIRTY);
144 }
145
146 /* (non-Javadoc)
147 * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
148 */
149 /**
150 * <p>isDirty</p>
151 *
152 * @return a boolean.
153 */
154 public boolean isDirty() {
155 return dirty;
156 }
157
158 /* (non-Javadoc)
159 * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
160 */
161 /** {@inheritDoc} */
162 @Override
163 public void editorDirtyStateChanged() {
164 dirty = true;
165 super.editorDirtyStateChanged();
166 }
167
168
169 /**
170 * {@inheritDoc}
171 *
172 * Checks whether nested editors are calling <code>firePropertyChange(PROP_DIRTY)</code>
173 * to signal an edit has taken place before passing property change along to
174 * <code>super.handlePropertyChange(int propertyId)</code>.
175 */
176 /* (non-Javadoc)
177 * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
178 */
179 protected void handlePropertyChange(int propertyId) {
180 if (propertyId == PROP_DIRTY) {
181 setDirty(true);
182 }
183 super.handlePropertyChange(propertyId);
184 }
185
186 /** {@inheritDoc} */
187 @Override
188 public void doSaveAs() {}
189
190 /** {@inheritDoc} */
191 @Override
192 public boolean isSaveAsAllowed() {
193 return false;
194 }
195
196 /** {@inheritDoc} */
197 @Override
198 public void init(IEditorSite site, IEditorInput input) throws PartInitException {
199
200 if (!(input instanceof TaxonEditorInput))
201 throw new PartInitException(
202 "Invalid Input: Must be TaxonEditorInput");
203
204 this.input = (TaxonEditorInput) input;
205
206 // try {
207 // // Listen for name changes,
208 // // change tab for this taxon editor accordingly
209 // getTaxon().addPropertyChangeListener("name",
210 // new PropertyChangeListener() {
211 // public void propertyChange(PropertyChangeEvent e) {
212 // setPartName();
213 // }
214 // });
215 // } catch (NullPointerException e) {
216 // EditorUtil.warn(getClass(), "Caught an NPE while initing an editor. This is most " +
217 // "likely due to the unsuccesful attempt to restore the former " +
218 // "state of the application. We ignore this because the workbench " +
219 // "will simply be reset.");
220 // }
221 setPartName();
222
223 super.init(site, input);
224 }
225
226 /**
227 * Calls <code>MultiPageEditorPart.setPartName(String partName)</code>
228 * with text appropriate to the state of the taxon: any taxon that has
229 * been saved will by necessity have a name to display; a new taxon
230 * should display "New taxon" in the editor tab.
231 */
232 protected void setPartName() {
233
234 String partName = null;
235 TaxonNameBase<?, ?> name = getTaxon().getName();
236
237 if (name != null) {
238 partName = name.getTitleCache();
239 }
240
241 if (partName == null || partName.equals("")) {
242 partName = ("New taxon");
243 }
244
245 setPartName(partName);
246 }
247
248 /**
249 * {@inheritDoc}
250 *
251 * Editor pages call this in their postOperation to notify the MultiPageTaxonEditor
252 * of unsaved changes
253 */
254 public void changed(Object element) {
255 // setDirty(true);
256 dirty = true;
257 super.editorDirtyStateChanged();
258 if(element instanceof TaxonBase){
259 TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
260 AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
261 if(container != null){
262 container.refresh();
263 }
264 }
265 }
266
267 /**
268 * The accepted taxon that is the input for this editor
269 *
270 * @return the accepted taxon
271 */
272 public Taxon getTaxon(){
273 return input.getTaxon();
274 }
275
276 /*
277 * (non-Javadoc)
278 * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
279 */
280 /**
281 * <p>getConversationHolder</p>
282 *
283 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
284 */
285 public ConversationHolder getConversationHolder() {
286 return conversation;
287 }
288
289 /**
290 * <p>setConversationHolder</p>
291 *
292 * @param conversation a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
293 */
294 public void setConversationHolder(ConversationHolder conversation){
295 this.conversation = conversation;
296 }
297
298
299 /**
300 * <p>Getter for the field <code>undoContext</code>.</p>
301 *
302 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
303 */
304 public IUndoContext getUndoContext() {
305 return undoContext;
306 }
307
308 /**
309 * <p>Setter for the field <code>undoContext</code>.</p>
310 *
311 * @param undoContext a {@link org.eclipse.core.commands.operations.IUndoContext} object.
312 */
313 public void setUndoContext(IUndoContext undoContext) {
314 this.undoContext = undoContext;
315 }
316
317 /** {@inheritDoc} */
318 @Override
319 public void setFocus(){
320 //logger.warn("Setting focus to editor");
321 // bind the conversation
322 getConversationHolder().bind();
323 // pass focus to the active editor page
324 getActiveEditor().setFocus();
325 }
326
327 /*
328 * (non-Javadoc)
329 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
330 */
331 /** {@inheritDoc} */
332 public void update(CdmDataChangeMap events) {
333 if(dataChangeBehavior == null){
334 dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
335 }
336
337 DataChangeBridge.handleDataChange(events, dataChangeBehavior);
338 }
339
340
341 /*
342 * (non-Javadoc)
343 * @see eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation()
344 */
345 /** {@inheritDoc} */
346 public boolean postOperation(CdmBase objectAffectedByOperation) {
347 setDirty(true);
348
349 for(IEditorPart editor : this.getPages()){
350 if (editor instanceof IPostOperationEnabled) {
351 ((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
352 } else {
353 EditorUtil.warn(getClass(), "postOperation not enabled for editor " + editor);
354 }
355 }
356 EditorUtil.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
357
358 return false;
359 }
360
361 /**
362 * Returns an <code>IEditorPart</code> implementation by type
363 *
364 * @param page the page type
365 * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage} object.
366 */
367 public IMultiPageTaxonEditorPage getPage(Page page){
368 for(IEditorPart editor : this.getPages()){
369 if(editor.getClass().equals(page.getClazz())){
370 return (IMultiPageTaxonEditorPage) editor;
371 }
372 }
373 return null;
374 }
375
376 /**
377 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
378 * <code>MultiPageTaxonEditor</code>.
379 *
380 * @return a {@link java.util.List} object.
381 */
382 public List<IMultiPageTaxonEditorPage> getPages(){
383 ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
384 for(int i = 0; i < this.getPageCount(); i++){
385
386 editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
387 }
388 return editors;
389 }
390
391 /**
392 * Refreshes a certain page of the MultipageTaxonEditor
393 *
394 * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
395 * @return a boolean.
396 */
397 public boolean redraw(Page page){
398 return redraw(page, true);
399 }
400
401 /**
402 * Refreshes a certain page of the MultipageTaxonEditor and
403 * sets focus to that page
404 *
405 * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
406 * @param focus a boolean.
407 * @return a boolean.
408 */
409 public boolean redraw(Page page, boolean focus){
410 IMultiPageTaxonEditorPage editorPage = getPage(page);
411 return editorPage != null && editorPage.redraw(focus);
412 }
413
414 /**
415 * <p>onComplete</p>
416 *
417 * @return a boolean.
418 */
419 public boolean onComplete() {
420 return false;
421 }
422
423 /**
424 * Reloads the data for this
425 */
426 public void reload() {
427 if(isDirty()){
428 EditorUtil.warningDialog("Editor has unsaved data", getClass(), "This editor can not be " +
429 "refreshed because it contains unsaved data. Refreshing " +
430 "this editor would discard the changes. Please save this editor, " +
431 "close and reopen it manually in order to get the latest content");
432 }else{
433 TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
434
435 UUID uuid = input.getTaxonNode().getUuid();
436
437 conversation.clear();
438
439 try {
440 TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
441 setInput(newInput);
442 for(IMultiPageTaxonEditorPage editorPart : getPages()){
443 editorPart.redraw();
444 }
445 } catch (Exception e) {
446 EditorUtil.errorDialog("Error refreshing editor", getClass(), "Could not refresh this editor", e);
447 }
448 }
449 }
450 }