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