factual data for bulkeditor, improving referencing objects view, make delete in bulke...
[taxeditor.git] / eu.etaxonomy.taxeditor.bulkeditor / src / main / java / eu / etaxonomy / taxeditor / bulkeditor / BulkEditor.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.taxeditor.bulkeditor;
12
13 import org.eclipse.core.runtime.IProgressMonitor;
14 import org.eclipse.jface.action.IMenuManager;
15 import org.eclipse.jface.dialogs.MessageDialog;
16 import org.eclipse.jface.dialogs.MessageDialogWithToggle;
17 import org.eclipse.jface.preference.IPreferenceStore;
18 import org.eclipse.jface.text.IDocument;
19 import org.eclipse.jface.text.ITextSelection;
20 import org.eclipse.jface.text.TextSelection;
21 import org.eclipse.jface.text.source.Annotation;
22 import org.eclipse.jface.text.source.AnnotationModel;
23 import org.eclipse.jface.text.source.ISourceViewer;
24 import org.eclipse.jface.text.source.IVerticalRuler;
25 import org.eclipse.jface.util.IPropertyChangeListener;
26 import org.eclipse.jface.window.Window;
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.custom.StyledText;
29 import org.eclipse.swt.events.MouseAdapter;
30 import org.eclipse.swt.events.MouseEvent;
31 import org.eclipse.swt.layout.GridData;
32 import org.eclipse.swt.layout.GridLayout;
33 import org.eclipse.swt.widgets.Composite;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.ui.IEditorInput;
36 import org.eclipse.ui.IEditorSite;
37 import org.eclipse.ui.IViewPart;
38 import org.eclipse.ui.PartInitException;
39 import org.eclipse.ui.PlatformUI;
40 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
41
42 import eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineDocumentProvider;
43 import eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineEditor;
44 import eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation;
45 import eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotationModel;
46 import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
47 import eu.etaxonomy.taxeditor.bulkeditor.referencingobjects.ReferencingObjectsView;
48 import eu.etaxonomy.taxeditor.model.IDerivedUnitFacadePart;
49 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
50 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
51 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
52
53 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
54 import eu.etaxonomy.taxeditor.store.CdmStore;
55
56 /**
57 * <p>
58 * BulkEditor class.
59 * </p>
60 *
61 * @author p.ciardelli
62 * @created 07.07.2009
63 * @version 1.0
64 */
65 public class BulkEditor extends AnnotatedLineEditor implements IPartContentHasDetails,
66 IDirtyMarkable, IDerivedUnitFacadePart, IPartContentHasFactualData {
67
68 /** Constant <code>ID="bulkeditor.editor"</code> */
69 public static final String ID = "bulkeditor.editor";
70
71 private boolean isInitialFocus = true;
72
73 private BulkEditorSearch searchBar = null;
74
75 private IPropertyChangeListener markerPreferenceListener;
76
77 private boolean isDirty;
78
79 /**
80 * <p>Constructor for BulkEditor.</p>
81 */
82 public BulkEditor() {
83 super(CdmStore.createConversation());
84 }
85
86 /* (non-Javadoc)
87 * @see org.eclipse.ui.editors.text.TextEditor#initializeEditor()
88 */
89 /** {@inheritDoc} */
90 @Override
91 protected void initializeEditor() {
92 super.initializeEditor();
93
94 /**
95 * see AbstractTextEditor javadoc for explanation of context menu ids
96 */
97 setEditorContextMenuId("#BulkEditorContext");
98
99 // setEntityCreatorService(new BulkEditorEntityCreatorService());
100
101 setLineDisplayStrategy(new BulkEditorLineDisplay(this));
102
103 setSourceViewerConfiguration(new BulkEditorViewerConfiguration(lineDisplayStrategy));
104 }
105
106 /* (non-Javadoc)
107 * @see eu.etaxonomy.taxeditor.bulkeditor.ListEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int)
108 */
109 /** {@inheritDoc} */
110 @Override
111 protected ISourceViewer createSourceViewer(Composite parent,
112 IVerticalRuler ruler, int styles) {
113 ISourceViewer viewer = super.createSourceViewer(parent, ruler, styles);
114 if (getEditorInput().isMergingEnabled()) {
115 addToggleMergeCandidateListener(ruler.getControl());
116 }
117 return viewer;
118 }
119
120 /* (non-Javadoc)
121 * @see eu.etaxonomy.taxeditor.bulkeditor.AnnotatedLineEditor#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
122 */
123 /** {@inheritDoc} */
124 @Override
125 public void init(IEditorSite site, IEditorInput input)
126 throws PartInitException {
127
128 if (!(input instanceof AbstractBulkEditorInput)) {
129 throw new PartInitException("Invalid Input: Must be BulkEditorInput");
130 }
131
132 super.init(site, input);
133 }
134
135 /* (non-Javadoc)
136 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite)
137 */
138 /** {@inheritDoc} */
139 @Override
140 public void createPartControl(Composite parent) {
141
142 parent.setLayout(new GridLayout());
143
144 Composite layoutComposite = new Composite(parent, SWT.NONE);
145 layoutComposite.setLayout(new GridLayout());
146
147 GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
148 layoutComposite.setLayoutData(gridData);
149
150 // layoutComposite.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE));
151
152
153 searchBar = new BulkEditorSearch(this, layoutComposite, SWT.NONE);
154 // layoutComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
155
156 super.createPartControl(parent);
157
158 // Set viewer composite to fill grid. Unfortunately it is private and we have to do a little hack here.
159 for (Control control : parent.getChildren()) {
160 if (control instanceof Composite &&
161 !(control.equals(layoutComposite))) {
162 control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
163 }
164 }
165 }
166
167 /* (non-Javadoc)
168 * @see org.eclipse.ui.editors.text.TextEditor#dispose()
169 */
170 /** {@inheritDoc} */
171 @Override
172 public void dispose() {
173 if (markerPreferenceListener != null ) {
174 PreferencesUtil.getPreferenceStore().removePropertyChangeListener(markerPreferenceListener);
175 }
176 super.dispose();
177 }
178
179
180 /* (non-Javadoc)
181 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#isEditable()
182 */
183 /** {@inheritDoc} */
184 @Override
185 public boolean isEditable() {
186 return false;
187 }
188
189 /* (non-Javadoc)
190 * @see eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineEditor#setFocus()
191 */
192 /** {@inheritDoc} */
193 @Override
194 public void setFocus() {
195 searchBar.setFocus();
196
197 // TODO find a better place to put this - this dialog should be shown after initial contents of
198 // Editor are displayed
199 if (isInitialFocus) {
200 displayWarningDialog();
201 isInitialFocus = false;
202 }
203 }
204
205 /**
206 *
207 */
208 private void displayWarningDialog() {
209 IPreferenceStore prefs = PreferencesUtil.getPreferenceStore();
210 if (!prefs.getBoolean(PreferencesUtil.HIDE_BULKEDITOR_INFO)) {
211 String msg = "The Bulk Editor allows you to edit objects used to reference other objects, such as names, references, and authors.\n\n" +
212 "Any changes you make to an object in the Bulk Editor will be displayed wherever the object is used.\n\n" +
213 "For instance, a reference may be displayed with both a name and a descriptive element. If the reference name is changed here, the display of both the name and the descriptive element will be affected.";
214 MessageDialogWithToggle dialog = MessageDialogWithToggle.openOkCancelConfirm
215 (getSite().getShell(), "Bulk Editor", msg, "Do not show this message again",
216 false, null, PreferencesUtil.HIDE_BULKEDITOR_INFO);
217 if (dialog.getReturnCode() == Window.OK) {
218 prefs.setValue(PreferencesUtil.HIDE_BULKEDITOR_INFO, dialog.getToggleState());
219 }
220 }
221 }
222
223 /**
224 * @param control
225 */
226 private void addToggleMergeCandidateListener(Control control) {
227 control.addMouseListener(new MouseAdapter() {
228 @Override
229 public void mouseDoubleClick(MouseEvent e) {
230 StyledText textWidget = getSourceViewer().getTextWidget();
231 int line = textWidget.getLineIndex(e.y);
232 toggleMergeCandidateAnnotation(line);
233 }
234 });
235 }
236
237 /**
238 * <p>toggleMergeCandidateAnnotation</p>
239 *
240 * @param line a int.
241 */
242 public void toggleMergeCandidateAnnotation(int line) {
243
244 IDocument document = getSourceViewer().getDocument();
245 LineAnnotationModel model =
246 (LineAnnotationModel) getSourceViewer().getAnnotationModel();
247
248 if(model != null){
249 Annotation annotation = model.getAnnotationAtLine(line, document);
250
251 if (annotation != null) {
252 if (annotation.getType().equals(IBulkEditorConstants.TYPE_MERGE_CANDIDATE)) {
253 model.changeAnnotationType(
254 annotation, LineAnnotation.TYPE_GENERIC);
255 } else {
256 model.changeAnnotationType(
257 annotation, IBulkEditorConstants.TYPE_MERGE_CANDIDATE);
258 }
259 }
260 }
261 }
262
263 /* (non-Javadoc)
264 * @see eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineEditor#isDirty()
265 */
266 @Override
267 public boolean isDirty() {
268 if(isDirty){
269 return isDirty;
270 }
271 else{
272 return super.isDirty();
273 }
274 }
275
276 @Override
277 public void forceDirty(){
278 isDirty = true;
279 firePropertyChange(PROP_DIRTY);
280 }
281
282 /* (non-Javadoc)
283 * @see eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineEditor#doSave(org.eclipse.core.runtime.IProgressMonitor)
284 */
285 @Override
286 public void doSave(IProgressMonitor progressMonitor) {
287 isDirty = false;
288 IViewPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
289 .findView("eu.etaxonomy.taxeditor.bulkeditor.view.referencingobjects");
290 if (part != null){
291 ((ReferencingObjectsView)part).dispose();
292 }
293 super.doSave(progressMonitor);
294
295 selectFirstItem();
296 if (part != null){
297 ((ReferencingObjectsView)part).refresh();
298
299 }
300 getSourceViewer().getTextWidget().setFocus();
301
302 }
303
304 /** {@inheritDoc} */
305 @Override
306 public void changed(Object object) {
307 // this.dirty = dirty;
308 AnnotatedLineDocumentProvider p = (AnnotatedLineDocumentProvider) getDocumentProvider();
309 p.changed(object);
310 // firePropertyChange(PROP_DIRTY);
311 }
312
313 /* (non-Javadoc)
314 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
315 */
316 /** {@inheritDoc} */
317 public void performSearch(BulkEditorQuery query) {
318 if (query != null) {
319
320 // TODO check if dirty, prompt save
321 if (isDirty()) {
322 boolean proceed = MessageDialog.openQuestion(getEditorSite().getShell(),
323 "Save changes", "You have made changes that must be saved before this query can be executed. Would you like to proceed?");
324 if (proceed) {
325 doSave(null);
326 } else {
327 return;
328 }
329 }
330
331 getEditorInput().performSearch(query);
332
333 refresh();
334
335 selectFirstItem();
336
337 getSourceViewer().getTextWidget().setFocus();
338 }
339 }
340
341 private void selectFirstItem() {
342 ITextSelection selection = new TextSelection(0, 0);
343 getSelectionProvider().setSelection(selection);
344 }
345
346 /**
347 *
348 */
349 public void refresh() {
350 if(getDocumentProvider().getAnnotationModel(getEditorInput()) != null){
351 ((AnnotationModel) getDocumentProvider().getAnnotationModel(getEditorInput())).removeAllAnnotations();
352 }
353
354 setInput(getEditorInput());
355 }
356
357 /** {@inheritDoc} */
358 @Override
359 public AbstractBulkEditorInput getEditorInput() {
360 return (AbstractBulkEditorInput) super.getEditorInput();
361 }
362
363 @Override
364 protected void editorContextMenuAboutToShow(IMenuManager menu) {
365 super.editorContextMenuAboutToShow(menu);
366 menu.remove(ITextEditorActionConstants.SHIFT_RIGHT);
367 menu.remove(ITextEditorActionConstants.SHIFT_LEFT);
368 menu.remove(ITextEditorActionConstants.CONTEXT_PREFERENCES);
369 }
370 }