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