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