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