fixes #888 and #889
[taxeditor.git] / 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.beans.PropertyChangeEvent;
13 import java.beans.PropertyChangeListener;
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import org.apache.log4j.Logger;
18 import org.eclipse.core.commands.operations.IUndoContext;
19 import org.eclipse.core.commands.operations.UndoContext;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.ui.IEditorInput;
22 import org.eclipse.ui.IEditorSite;
23 import org.eclipse.ui.PartInitException;
24 import org.eclipse.ui.part.MultiPageEditorPart;
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.persistence.hibernate.CdmDataChangeMap;
32 import eu.etaxonomy.taxeditor.editor.description.TaxonDescriptionEditor;
33 import eu.etaxonomy.taxeditor.editor.images.TaxonImageEditor;
34 import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
35 import eu.etaxonomy.taxeditor.model.DataChangeBridge;
36 import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
37 import eu.etaxonomy.taxeditor.operations.IPostOperationEnabled;
38
39 /**
40 *
41 * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs for
42 * "Descriptions", "Concepts", "Geography", etc.
43 *
44 * @author p.ciardelli
45 * @author n.hoffmann
46 * @created 15.05.2008
47 * @version 1.0
48 */
49 public class MultiPageTaxonEditor extends MultiPageEditorPart implements IConversationEnabled, IPostOperationEnabled {
50 private static final Logger logger = Logger.getLogger(MultiPageTaxonEditor.class);
51
52 public static final String ID = "eu.etaxonomy.taxeditor.editor.multipagetaxonview";
53
54 private boolean dirty;
55
56 private ConversationHolder conversation;
57 private IDataChangeBehavior dataChangeBehavior;
58 private IUndoContext undoContext;
59
60 private TaxonEditorInput input;
61
62
63 public MultiPageTaxonEditor() {
64 super();
65 undoContext = new UndoContext();
66 }
67
68
69
70 @Override
71 public void dispose() {
72 super.dispose();
73 // EditorUtil.checkHidePropertySheet();
74 }
75
76 @Override
77 protected void createPages() {
78
79 input = (TaxonEditorInput) getEditorInput();
80 conversation = input.getConversationHolder();
81 conversation.registerForDataStoreChanges(this);
82
83 try {
84 addPage(Page.NAME.getIndex(), new TaxonNameEditor(this), getEditorInput());
85 setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
86
87 // TODO lazy create
88 addPage(Page.DESCRIPTIVE.getIndex(), new TaxonDescriptionEditor(this), getEditorInput());
89 setPageText(Page.DESCRIPTIVE.getIndex(), Page.DESCRIPTIVE.getTitle());
90
91 // TODO lazy create
92 addPage(Page.IMAGE.getIndex(), new TaxonImageEditor(this), getEditorInput());
93 setPageText(Page.IMAGE.getIndex(), Page.IMAGE.getTitle());
94
95 EditorUtil.showPropertySheet();
96
97 } catch (PartInitException e) {
98 logger.error("Could not create MultiPageTaxonEditor.", e);
99 }
100 }
101
102 @Override
103 public void doSave(IProgressMonitor monitor) {
104
105 //handle existing names and authors
106 DuplicateArbitrator duplicateArbitrator = (DuplicateArbitrator) getAdapter(DuplicateArbitrator.class);
107
108 if(duplicateArbitrator != null){
109 // disable for now because of transaction problems.
110 // duplicateArbitrator.arbitrate();
111 }
112
113
114 if( ! conversation.isBound()){
115 conversation.bind();
116 }
117
118 // commit the conversation and start a new transaction immediately
119 conversation.commit(true);
120
121 this.setDirty(false);
122 }
123
124 private void setDirty(boolean dirty) {
125 this.dirty = dirty;
126 firePropertyChange(PROP_DIRTY);
127 }
128
129 /* (non-Javadoc)
130 * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
131 */
132 public boolean isDirty() {
133 return dirty;
134 }
135
136 /**
137 * Checks whether nested editors are calling <code>firePropertyChange(PROP_DIRTY)</code>
138 * to signal an edit has taken place before passing property change along to
139 * <code>super.handlePropertyChange(int propertyId)</code>.
140 */
141 /* (non-Javadoc)
142 * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
143 */
144 protected void handlePropertyChange(int propertyId) {
145 if (propertyId == PROP_DIRTY) {
146 setDirty(true);
147 }
148 super.handlePropertyChange(propertyId);
149 }
150
151 @Override
152 public void doSaveAs() {}
153
154 @Override
155 public boolean isSaveAsAllowed() {
156 return false;
157 }
158
159 @Override
160 public void init(IEditorSite site, IEditorInput input) throws PartInitException {
161
162 if (!(input instanceof TaxonEditorInput))
163 throw new PartInitException(
164 "Invalid Input: Must be TaxonEditorInput");
165
166 // FIXME looks like we do it differently now
167 // Get taxon from editor input
168 // if (input.getAdapter(Taxon.class) != null) {
169 // taxon = (Taxon) input.getAdapter(Taxon.class);
170 // } else {
171 // taxon = null;
172 // }
173
174 this.input = (TaxonEditorInput) input;
175
176 try {
177 // Listen for name changes,
178 // change tab for this taxon editor accordingly
179 getTaxon().addPropertyChangeListener("name",
180 new PropertyChangeListener() {
181 public void propertyChange(PropertyChangeEvent e) {
182 setPartName();
183 }
184 });
185 } catch (NullPointerException e) {
186 logger.warn("Caught an NPE while initing an editor. This is most " +
187 "likely due to the unsuccesful attempt to restore the former " +
188 "state of the application. We ignore this because the workbench " +
189 "will simply be reset.");
190 }
191 setPartName();
192
193 super.init(site, input);
194 }
195
196 /**
197 * Calls <code>MultiPageEditorPart.setPartName(String partName)</code>
198 * with text appropriate to the state of the taxon: any taxon that has
199 * been saved will by necessity have a name to display; a new taxon
200 * should display "New taxon" in the editor tab.
201 */
202 protected void setPartName() {
203
204 String partName = null;
205 TaxonNameBase<?, ?> name = getTaxon().getName();
206
207 if (name != null) {
208 partName = name.getTitleCache();
209 }
210
211 if (partName == null || partName.equals("")) {
212 partName = ("New taxon");
213 }
214
215 setPartName(partName);
216 }
217
218 /**
219 * Editor pages call this in their postOperation to notify the MultiPageTaxonEditor
220 * of unsaved changes
221 */
222 public void setDirty() {
223 setDirty(true);
224 }
225
226 public Taxon getTaxon(){
227 return input.getTaxon();
228 }
229
230 /*
231 * (non-Javadoc)
232 * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
233 */
234 public ConversationHolder getConversationHolder() {
235 return conversation;
236 }
237
238 public void setConversationHolder(ConversationHolder conversation){
239 this.conversation = conversation;
240 }
241
242
243 public IUndoContext getUndoContext() {
244 return undoContext;
245 }
246
247 public void setUndoContext(IUndoContext undoContext) {
248 this.undoContext = undoContext;
249 }
250
251 @Override
252 public void setFocus(){
253 // bind the conversation
254 getConversationHolder().bind();
255 // pass focus to the active editor page
256 getActiveEditorPage().setFocus();
257 }
258
259 public AbstractTaxonEditor getActiveEditorPage(){
260 return (AbstractTaxonEditor) getEditor(getActivePage());
261 }
262
263 /*
264 * (non-Javadoc)
265 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
266 */
267 public void update(CdmDataChangeMap events) {
268 if(dataChangeBehavior == null){
269 dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
270 }
271
272 DataChangeBridge.handleDataChange(events, dataChangeBehavior);
273 }
274
275
276 /*
277 * (non-Javadoc)
278 * @see eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation()
279 */
280 public boolean postOperation(CdmBase objectAffectedByOperation) {
281 setDirty(true);
282
283 for(AbstractTaxonEditor editor : this.getPages()){
284 editor.postOperation(objectAffectedByOperation);
285 }
286 logger.warn("postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
287
288 return false;
289 }
290
291 /**
292 * Returns an <code>AbstractTaxonEditor</code> implementation by type
293 *
294 * @param page the page type
295 * @return
296 */
297 public AbstractTaxonEditor getPage(Page page){
298 for(AbstractTaxonEditor editor : this.getPages()){
299 if(editor.getClass().equals(page.getClazz())){
300 return editor;
301 }
302 }
303 return null;
304 }
305
306 /**
307 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
308 * <code>MultiPageTaxonEditor</code>.
309 *
310 * @return
311 */
312 public List<AbstractTaxonEditor> getPages(){
313 ArrayList<AbstractTaxonEditor> editors = new ArrayList<AbstractTaxonEditor>();
314 for(int i = 0; i < this.getPageCount(); i++){
315 editors.add((AbstractTaxonEditor) this.getEditor(i));
316 }
317 return editors;
318 }
319 }