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