Project

General

Profile

Download (12.8 KB) Statistics
| Branch: | Tag: | Revision:
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.jface.viewers.StructuredSelection;
21
import org.eclipse.ui.IEditorInput;
22
import org.eclipse.ui.IEditorPart;
23
import org.eclipse.ui.IEditorSite;
24
import org.eclipse.ui.PartInitException;
25
import org.eclipse.ui.forms.editor.FormEditor;
26

    
27
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
28
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
29
import eu.etaxonomy.cdm.model.common.CdmBase;
30
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
31
import eu.etaxonomy.cdm.model.taxon.Taxon;
32
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
33
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
34
import eu.etaxonomy.taxeditor.editor.name.TaxonNameEditor;
35
import eu.etaxonomy.taxeditor.editor.name.container.AbstractGroupedContainer;
36
import eu.etaxonomy.taxeditor.model.DataChangeBridge;
37
import eu.etaxonomy.taxeditor.model.IDataChangeBehavior;
38
import eu.etaxonomy.taxeditor.model.IDirtyMarkableSelectionProvider;
39
import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
40
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
41

    
42
/**
43
 *
44
 * Generates the tabbed editor with <code>TaxonNameEditor</code> on top and tabs for
45
 *  "Descriptions", "Concepts", "Geography", etc.
46
 *
47
 * @author p.ciardelli
48
 * @author n.hoffmann
49
 * @created 15.05.2008
50
 * @version 1.0
51
 */
52
public class MultiPageTaxonEditor extends FormEditor implements IConversationEnabled, IPostOperationEnabled, IDirtyMarkableSelectionProvider, IPartContentHasDetails {	
53

    
54
	/** Constant <code>ID="eu.etaxonomy.taxeditor.editor.taxon"{trunked}</code> */
55
	public static final String ID = "eu.etaxonomy.taxeditor.editor.taxon";
56

    
57
	private boolean dirty;
58

    
59
	private ConversationHolder conversation;
60
	private IDataChangeBehavior dataChangeBehavior;
61
	private IUndoContext undoContext;
62

    
63
	private TaxonEditorInput input;
64
	
65
	/**
66
	 * <p>Constructor for MultiPageTaxonEditor.</p>
67
	 */
68
	public MultiPageTaxonEditor() {
69
		super();		
70
		undoContext = new UndoContext();
71
	}
72
	
73
	/** {@inheritDoc} */
74
	@Override
75
	public void dispose() {
76
		conversation.unregisterForDataStoreChanges(this);
77
		conversation.close();
78
		super.dispose();		
79
	}
80

    
81
	/* (non-Javadoc)
82
	 * @see org.eclipse.ui.forms.editor.FormEditor#addPages()
83
	 */
84
	/** {@inheritDoc} */
85
	@Override
86
	protected void addPages() {
87
		input = (TaxonEditorInput) getEditorInput();
88
		conversation = input.getConversationHolder();
89
		conversation.registerForDataStoreChanges(this);
90
		
91
		try {
92
			addPage(Page.NAME.getIndex(), new TaxonNameEditor(this), getEditorInput());
93
//			setPageText(Page.NAME.getIndex(), Page.NAME.getTitle());
94
			
95
			// TODO lazy create
96
//			addPage(Page.DESCRIPTIVE.getIndex(), new TaxonDescriptionTreeEditor(this), getEditorInput());
97
//			setPageText(Page.DESCRIPTIVE.getIndex(), Page.DESCRIPTIVE.getTitle());
98
			
99
//			EditorUtil.showPropertySheet();
100
					
101
		} catch (PartInitException e) {
102
			EditorUtil.error(getClass(), e);
103
		}
104
	}
105
	
106
	
107
	/** {@inheritDoc} */
108
	@Override
109
	public void doSave(IProgressMonitor monitor) {
110
		monitor.beginTask("Saving Editor", 4);
111
		try{
112
			if( ! conversation.isBound()){
113
				conversation.bind();
114
			}
115
			monitor.worked(1);
116
			
117
			for(IEditorPart editorPage : getPages()){
118
				if(editorPage instanceof TaxonNameEditor){
119
					if(((TaxonNameEditor) editorPage).checkForEmptyNames()){
120
						MessageDialog.openWarning(EditorUtil.getShell(), "No Name Specified", "An attempt was made to save a taxon or synonym with " +
121
						"an empty name. Operation was cancelled.");
122
						return;
123
					}
124
				}
125
	
126
				editorPage.doSave(monitor);
127
				monitor.worked(1);
128
			}
129
			
130
			// commit the conversation and start a new transaction immediately
131
			conversation.commit(true);
132
			monitor.worked(1);
133
			
134
			this.setDirty(false);
135
			monitor.worked(1);
136
		}catch(Exception e){
137
			EditorUtil.errorDialog("An error occurred while saving", getClass(), "An error occurred while saving the editor. Please close and reopen the taxon again.", e);
138
			disableEditor();
139
		}finally{
140
			monitor.done();
141
		}
142
	}
143

    
144

    
145
	private void disableEditor() {
146
		for(IMultiPageTaxonEditorPage editorPage : getPages()){
147
			editorPage.setDisabled();
148
		}
149
		setDirty(false);
150
		getSite().getSelectionProvider().setSelection(new StructuredSelection());
151
		getSite().setSelectionProvider(null);
152
	}
153

    
154
	private void setDirty(boolean dirty) {
155
		this.dirty = dirty;
156
		firePropertyChange(PROP_DIRTY);
157
	}
158
	
159
	/* (non-Javadoc)
160
	 * @see org.eclipse.ui.part.MultiPageEditorPart#isDirty()
161
	 */
162
	/**
163
	 * <p>isDirty</p>
164
	 *
165
	 * @return a boolean.
166
	 */
167
	public boolean isDirty() {
168
		return dirty;
169
	}
170

    
171
	/* (non-Javadoc)
172
	 * @see org.eclipse.ui.forms.editor.FormEditor#editorDirtyStateChanged()
173
	 */
174
	/** {@inheritDoc} */
175
	@Override
176
	public void editorDirtyStateChanged() {
177
		dirty = true;
178
		super.editorDirtyStateChanged();
179
	}
180
	
181
	
182
	/**
183
	 * {@inheritDoc}
184
	 *
185
	 * Checks whether nested editors are calling <code>firePropertyChange(PROP_DIRTY)</code>
186
	 * to signal an edit has taken place before passing property change along to
187
	 * <code>super.handlePropertyChange(int propertyId)</code>.
188
	 */
189
	/* (non-Javadoc)
190
	 * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int)
191
	 */
192
	protected void handlePropertyChange(int propertyId) {
193
		if (propertyId == PROP_DIRTY) {
194
			setDirty(true);
195
		}
196
		super.handlePropertyChange(propertyId);
197
	}
198
	
199
	/** {@inheritDoc} */
200
	@Override
201
	public void doSaveAs() {}
202

    
203
	/** {@inheritDoc} */
204
	@Override
205
	public boolean isSaveAsAllowed() {
206
		return false;
207
	}
208

    
209
	/** {@inheritDoc} */
210
	@Override
211
	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
212
		
213
		if (!(input instanceof TaxonEditorInput))
214
			throw new PartInitException(
215
					"Invalid Input: Must be TaxonEditorInput");
216
		
217
		this.input = (TaxonEditorInput) input;
218

    
219
//		try {
220
//			// Listen for name changes, 
221
//			//  change tab for this taxon editor accordingly
222
//			getTaxon().addPropertyChangeListener("name",
223
//					new PropertyChangeListener() {
224
//						public void propertyChange(PropertyChangeEvent e) {
225
//							setPartName();
226
//						}
227
//					});
228
//		} catch (NullPointerException e) {
229
//			EditorUtil.warn(getClass(), "Caught an NPE while initing an editor. This is most " +
230
//					"likely due to the unsuccesful attempt to restore the former " +
231
//					"state of the application. We ignore this because the workbench " +
232
//					"will simply be reset.");
233
//		}
234
		setPartName();
235
		
236
		super.init(site, input);
237
	}
238
		
239
    /**
240
     * Calls <code>MultiPageEditorPart.setPartName(String partName)</code>
241
     *  with text appropriate to the state of the taxon: any taxon that has
242
     *  been saved will by necessity have a name to display; a new taxon
243
     *  should display "New taxon" in the editor tab.
244
     */
245
    protected void setPartName() {
246
        
247
    	String partName = null;
248
    	TaxonNameBase<?, ?> name = getTaxon().getName();
249
    	
250
    	if (name != null) {
251
    		partName = name.getTitleCache();
252
    	}
253
    	
254
    	if (partName == null || partName.equals("")) {
255
    		partName = ("New taxon");
256
    	}
257

    
258
        setPartName(partName);
259
    }
260
    
261
    /**
262
     * {@inheritDoc}
263
     *
264
     * Editor pages call this in their postOperation to notify the MultiPageTaxonEditor
265
     * of unsaved changes
266
     */
267
    public void changed(Object element) {
268
//    	setDirty(true);
269
		dirty = true;
270
		super.editorDirtyStateChanged();
271
		if(element instanceof TaxonBase){
272
			TaxonNameEditor page = (TaxonNameEditor) getPage(Page.NAME);
273
			AbstractGroupedContainer container = page.getContainer((TaxonBase) element);
274
			if(container != null){
275
				container.refresh();
276
			}
277
		}
278
    }
279
    
280
    /**
281
     * The accepted taxon that is the input for this editor
282
     *
283
     * @return the accepted taxon
284
     */
285
    public Taxon getTaxon(){
286
    	return input.getTaxon();
287
    }
288

    
289
    /*
290
     * (non-Javadoc)
291
     * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
292
     */
293
	/**
294
	 * <p>getConversationHolder</p>
295
	 *
296
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
297
	 */
298
	public ConversationHolder getConversationHolder() {
299
		return conversation;
300
	}
301
	
302
	/**
303
	 * <p>setConversationHolder</p>
304
	 *
305
	 * @param conversation a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
306
	 */
307
	public void setConversationHolder(ConversationHolder conversation){
308
		this.conversation = conversation;
309
	}
310

    
311

    
312
	/**
313
	 * <p>Getter for the field <code>undoContext</code>.</p>
314
	 *
315
	 * @return a {@link org.eclipse.core.commands.operations.IUndoContext} object.
316
	 */
317
	public IUndoContext getUndoContext() {
318
		return undoContext;
319
	}
320

    
321
	/**
322
	 * <p>Setter for the field <code>undoContext</code>.</p>
323
	 *
324
	 * @param undoContext a {@link org.eclipse.core.commands.operations.IUndoContext} object.
325
	 */
326
	public void setUndoContext(IUndoContext undoContext) {
327
		this.undoContext = undoContext;
328
	}
329
	
330
	/** {@inheritDoc} */
331
	@Override
332
	public void setFocus(){
333
		//logger.warn("Setting focus to editor");
334
		// bind the conversation
335
		getConversationHolder().bind();
336
		// pass focus to the active editor page
337
		getActiveEditor().setFocus();
338
	}
339

    
340
	/*
341
	 * (non-Javadoc)
342
	 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostCrudObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmCrudEvent)
343
	 */
344
	/** {@inheritDoc} */
345
	public void update(CdmDataChangeMap events) {
346
		if(dataChangeBehavior == null){
347
			dataChangeBehavior = new MultiPageTaxonEditorDataChangeBehaviour(this);
348
		}
349
		
350
		DataChangeBridge.handleDataChange(events, dataChangeBehavior);
351
	}
352

    
353

    
354
	/*
355
	 * (non-Javadoc)
356
	 * @see eu.etaxonomy.taxeditor.store.operations.IPostOperationEnabled#postOperation()
357
	 */
358
	/** {@inheritDoc} */
359
	public boolean postOperation(CdmBase objectAffectedByOperation) {
360
		setDirty(true);
361
		
362
		for(IEditorPart editor : this.getPages()){
363
			if (editor instanceof IPostOperationEnabled) {
364
				((IPostOperationEnabled) editor).postOperation(objectAffectedByOperation);
365
			} else {
366
				EditorUtil.warn(getClass(), "postOperation not enabled for editor " + editor);
367
			}
368
		}
369
		EditorUtil.warn(getClass(), "postOperation called on MultiPageTaxonEditor. Can you make it more specific?");
370
		
371
		return false;
372
	}
373
	
374
	/**
375
	 * Returns an <code>IEditorPart</code> implementation by type
376
	 *
377
	 * @param page the page type
378
	 * @return a {@link eu.etaxonomy.taxeditor.editor.IMultiPageTaxonEditorPage} object.
379
	 */
380
	public IMultiPageTaxonEditorPage getPage(Page page){
381
		for(IEditorPart editor : this.getPages()){
382
		 	if(editor.getClass().equals(page.getClazz())){
383
		 		return (IMultiPageTaxonEditorPage) editor;
384
		 	}
385
		}
386
		return null;
387
	}
388
	
389
	/**
390
	 * Return a list of <code>AbstractTaxonEditor</code>s registered with this
391
	 * <code>MultiPageTaxonEditor</code>.
392
	 *
393
	 * @return a {@link java.util.List} object.
394
	 */
395
	public List<IMultiPageTaxonEditorPage> getPages(){
396
		ArrayList<IMultiPageTaxonEditorPage> editors = new ArrayList<IMultiPageTaxonEditorPage>();
397
		for(int i = 0; i < this.getPageCount(); i++){
398
			
399
		 	editors.add((IMultiPageTaxonEditorPage) this.getEditor(i));
400
		}
401
		return editors;
402
	}
403
	
404
	/**
405
	 * Refreshes a certain page of the MultipageTaxonEditor
406
	 *
407
	 * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
408
	 * @return a boolean.
409
	 */
410
	public boolean redraw(Page page){
411
		return redraw(page, true);
412
	}
413
	
414
	/**
415
	 * Refreshes a certain page of the MultipageTaxonEditor and
416
	 * sets focus to that page
417
	 *
418
	 * @param page a {@link eu.etaxonomy.taxeditor.editor.Page} object.
419
	 * @param focus a boolean.
420
	 * @return a boolean.
421
	 */
422
	public boolean redraw(Page page, boolean focus){
423
		IMultiPageTaxonEditorPage editorPage = getPage(page);
424
		return editorPage != null && editorPage.redraw(focus);
425
	}
426

    
427
	/**
428
	 * <p>onComplete</p>
429
	 *
430
	 * @return a boolean.
431
	 */
432
	public boolean onComplete() {
433
		return false;
434
	}
435

    
436
	/**
437
	 * Reloads the data for this 
438
	 */
439
	public void reload() {
440
		if(isDirty()){
441
			EditorUtil.warningDialog("Editor has unsaved data", getClass(), "This editor can not be " +
442
					"refreshed because it contains unsaved data. Refreshing " +
443
					"this editor would discard the changes. Please save this editor, " +
444
					"close and reopen it manually in order to get the latest content");
445
		}else{
446
			TaxonEditorInput input = (TaxonEditorInput) getEditorInput();
447
			
448
			UUID uuid = input.getTaxonNode().getUuid();
449
			
450
			conversation.clear();
451
			
452
			try {
453
				TaxonEditorInput newInput = TaxonEditorInput.NewInstance(uuid);
454
				setInput(newInput);
455
				for(IMultiPageTaxonEditorPage editorPart : getPages()){
456
					editorPart.redraw();
457
				}
458
			} catch (Exception e) {
459
				EditorUtil.errorDialog("Error refreshing editor", getClass(), "Could not refresh this editor", e);
460
			}
461
		}
462
	}
463
}
(7-7/16)