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