adapting to chages in CdmUtils
[taxeditor.git] / eu.etaxonomy.taxeditor.bulkeditor / src / main / java / eu / etaxonomy / taxeditor / bulkeditor / BulkEditor.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.taxeditor.bulkeditor;
11
12 import org.eclipse.core.commands.operations.IUndoContext;
13 import org.eclipse.core.commands.operations.UndoContext;
14 import org.eclipse.core.runtime.IProgressMonitor;
15 import org.eclipse.jface.action.IMenuManager;
16 import org.eclipse.jface.dialogs.MessageDialog;
17 import org.eclipse.jface.dialogs.MessageDialogWithToggle;
18 import org.eclipse.jface.preference.IPreferenceStore;
19 import org.eclipse.jface.text.IDocument;
20 import org.eclipse.jface.text.ITextSelection;
21 import org.eclipse.jface.text.TextSelection;
22 import org.eclipse.jface.text.source.Annotation;
23 import org.eclipse.jface.text.source.AnnotationModel;
24 import org.eclipse.jface.text.source.ISourceViewer;
25 import org.eclipse.jface.text.source.IVerticalRuler;
26 import org.eclipse.jface.util.IPropertyChangeListener;
27 import org.eclipse.jface.window.Window;
28 import org.eclipse.swt.SWT;
29 import org.eclipse.swt.custom.StyledText;
30 import org.eclipse.swt.events.MouseAdapter;
31 import org.eclipse.swt.events.MouseEvent;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.widgets.Composite;
35 import org.eclipse.swt.widgets.Control;
36 import org.eclipse.ui.IEditorInput;
37 import org.eclipse.ui.IEditorSite;
38 import org.eclipse.ui.PartInitException;
39 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
40
41 import eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineDocumentProvider;
42 import eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineEditor;
43 import eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotation;
44 import eu.etaxonomy.taxeditor.annotatedlineeditor.LineAnnotationModel;
45 import eu.etaxonomy.taxeditor.bulkeditor.input.AbstractBulkEditorInput;
46 import eu.etaxonomy.taxeditor.bulkeditor.input.OccurrenceEditorInput;
47 import eu.etaxonomy.taxeditor.bulkeditor.input.TaxonEditorInput;
48 import eu.etaxonomy.taxeditor.model.IDerivedUnitFacadePart;
49 import eu.etaxonomy.taxeditor.model.IDirtyMarkable;
50 import eu.etaxonomy.taxeditor.model.IPartContentHasDetails;
51 import eu.etaxonomy.taxeditor.model.IPartContentHasFactualData;
52 import eu.etaxonomy.taxeditor.model.IPartContentHasMedia;
53 import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
54 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
55 import eu.etaxonomy.taxeditor.store.CdmStore;
56
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 private IUndoContext undoContext;
77
78 public BulkEditor() {
79 super(CdmStore.createConversation());
80 undoContext = new UndoContext();
81 }
82
83 /** {@inheritDoc} */
84 @Override
85 protected void initializeEditor() {
86 super.initializeEditor();
87
88 /**
89 * see AbstractTextEditor javadoc for explanation of context menu ids
90 */
91 setEditorContextMenuId("#BulkEditorContext");
92
93 // setEntityCreatorService(new BulkEditorEntityCreatorService());
94
95 setLineDisplayStrategy(new BulkEditorLineDisplay(this));
96
97 setSourceViewerConfiguration(new BulkEditorViewerConfiguration(lineDisplayStrategy));
98 }
99
100 /** {@inheritDoc} */
101 @Override
102 protected ISourceViewer createSourceViewer(Composite parent,
103 IVerticalRuler ruler, int styles) {
104 ISourceViewer viewer = super.createSourceViewer(parent, ruler, styles);
105 if (getEditorInput().isMergingEnabled()) {
106 addToggleMergeCandidateListener(ruler.getControl());
107 }
108 return viewer;
109 }
110
111 /** {@inheritDoc} */
112 @Override
113 public void init(IEditorSite site, IEditorInput input)
114 throws PartInitException {
115
116 if (!(input instanceof AbstractBulkEditorInput)) {
117 throw new PartInitException("Invalid Input: Must be BulkEditorInput");
118 }
119 else{
120 AbstractBulkEditorInput<?> bulkEditorInput = (AbstractBulkEditorInput<?>)input;
121 if(bulkEditorInput.getEntityUuid()!=null){
122 bulkEditorInput.performSearch(new BulkEditorQuery(bulkEditorInput.getEntityUuid().toString(), null));
123 }
124 }
125 super.init(site, input);
126 }
127
128 /** {@inheritDoc} */
129 @Override
130 public void createPartControl(Composite parent) {
131
132 parent.setLayout(new GridLayout());
133
134 Composite layoutComposite = new Composite(parent, SWT.NONE);
135 layoutComposite.setLayout(new GridLayout());
136
137 GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
138 layoutComposite.setLayoutData(gridData);
139
140 // layoutComposite.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_BLUE));
141
142
143 searchBar = new BulkEditorSearch(this, layoutComposite, SWT.NONE);
144 // layoutComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
145
146 super.createPartControl(parent);
147
148 // Set viewer composite to fill grid. Unfortunately it is private and we have to do a little hack here.
149 for (Control control : parent.getChildren()) {
150 if (control instanceof Composite &&
151 !(control.equals(layoutComposite))) {
152 control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
153 }
154 }
155 }
156
157 /** {@inheritDoc} */
158 @Override
159 public void dispose() {
160 if (markerPreferenceListener != null ) {
161 PreferencesUtil.getPreferenceStore().removePropertyChangeListener(markerPreferenceListener);
162 }
163 super.dispose();
164 }
165
166
167 /** {@inheritDoc} */
168 @Override
169 public boolean isEditable() {
170 return false;
171 }
172
173 /** {@inheritDoc} */
174 @Override
175 public void setFocus() {
176 conversation.bind();
177
178 // TODO find a better place to put this - this dialog should be shown after initial contents of
179 // Editor are displayed
180 if (isInitialFocus) {
181 displayWarningDialog();
182 isInitialFocus = false;
183 }
184 super.setFocus();
185 searchBar.setFocus();
186 }
187
188 /**
189 * @return the searchBar
190 */
191 public BulkEditorSearch getSearchBar() {
192 return searchBar;
193 }
194
195 private void displayWarningDialog() {
196 IPreferenceStore prefs = PreferencesUtil.getPreferenceStore();
197 if (!prefs.getBoolean(IPreferenceKeys.HIDE_BULKEDITOR_INFO)) {
198 String msg = "The Bulk Editor allows you to edit objects used to reference other objects, such as names, references, and authors.\n\n" +
199 "Any changes you make to an object in the Bulk Editor will be displayed wherever the object is used.\n\n" +
200 "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.";
201 MessageDialogWithToggle dialog = MessageDialogWithToggle.openOkCancelConfirm
202 (getSite().getShell(), "Bulk Editor", msg, "Do not show this message again",
203 false, null, IPreferenceKeys.HIDE_BULKEDITOR_INFO);
204 if (dialog.getReturnCode() == Window.OK) {
205 prefs.setValue(IPreferenceKeys.HIDE_BULKEDITOR_INFO, dialog.getToggleState());
206 }
207 }
208 }
209
210 private void addToggleMergeCandidateListener(Control control) {
211 control.addMouseListener(new MouseAdapter() {
212 @Override
213 public void mouseDoubleClick(MouseEvent e) {
214 StyledText textWidget = getSourceViewer().getTextWidget();
215 int line = textWidget.getLineIndex(e.y);
216 toggleMergeCandidateAnnotation(line);
217 }
218 });
219 }
220
221 public void toggleMergeCandidateAnnotation(int line) {
222
223 IDocument document = getSourceViewer().getDocument();
224 LineAnnotationModel model =
225 (LineAnnotationModel) getSourceViewer().getAnnotationModel();
226
227 if(model != null){
228 Annotation annotation = model.getAnnotationAtLine(line, document);
229
230 if (annotation != null) {
231 if (annotation.getType().equals(IBulkEditorConstants.TYPE_MERGE_CANDIDATE)) {
232 model.changeAnnotationType(
233 annotation, LineAnnotation.TYPE_GENERIC);
234 } else {
235 model.changeAnnotationType(
236 annotation, IBulkEditorConstants.TYPE_MERGE_CANDIDATE);
237 }
238 }
239 }
240 }
241
242 @Override
243 public boolean isDirty() {
244 if(isDirty){
245 return isDirty;
246 }
247 else{
248 return super.isDirty();
249 }
250 }
251
252 @Override
253 public void forceDirty(){
254 isDirty = true;
255 firePropertyChange(PROP_DIRTY);
256 }
257
258
259 @Override
260 public void doSave(IProgressMonitor progressMonitor) {
261 isDirty = false;
262
263 super.doSave(progressMonitor);
264
265 selectFirstItem();
266
267 getSourceViewer().getTextWidget().setFocus();
268
269 }
270
271 /** {@inheritDoc} */
272 @Override
273 public void changed(Object object) {
274 // this.dirty = dirty;
275 AnnotatedLineDocumentProvider p = (AnnotatedLineDocumentProvider) getDocumentProvider();
276 p.changed(object);
277 // firePropertyChange(PROP_DIRTY);
278 }
279
280 /** {@inheritDoc} */
281 public void performSearch(BulkEditorQuery query) {
282 if (query != null) {
283
284 // TODO check if dirty, prompt save
285 if (isDirty()) {
286 String[] labels = {"Save (and Search)", "Don't save (and Search)","Cancel"};
287 MessageDialog dialog =new MessageDialog(getEditorSite().getShell(), "Save changes", null, "You have made changes that must be saved before this query can be executed. Would you like to proceed?", MessageDialog.QUESTION,labels, 0);
288 int result = dialog.open();
289 //MessageDialog.openQuestion(getEditorSite().getShell(),
290 //"Save changes", "You have made changes that must be saved before this query can be executed. Would you like to proceed?");
291 if (result == 0) {
292 doSave(null);
293 } else if (result == 2){
294 return;
295 }
296 }
297 //conversation.clear();
298 //conversation.commit(true);
299
300 getEditorInput().dispose();
301 getEditorInput().bind();
302 getEditorInput().performSearch(query);
303
304 refresh();
305
306 selectFirstItem();
307
308 getSourceViewer().getTextWidget().setFocus();
309 }
310 }
311
312 private void selectFirstItem() {
313 ITextSelection selection = new TextSelection(0, 0);
314 getSelectionProvider().setSelection(selection);
315 }
316
317 public void refresh() {
318 if(getDocumentProvider().getAnnotationModel(getEditorInput()) != null){
319 ((AnnotationModel) getDocumentProvider().getAnnotationModel(getEditorInput())).removeAllAnnotations();
320 }
321
322 setInput(getEditorInput());
323 }
324
325 /** {@inheritDoc} */
326 @Override
327 public AbstractBulkEditorInput getEditorInput() {
328 return (AbstractBulkEditorInput) super.getEditorInput();
329 }
330
331 @Override
332 protected void editorContextMenuAboutToShow(IMenuManager menu) {
333 super.editorContextMenuAboutToShow(menu);
334 menu.remove(ITextEditorActionConstants.SHIFT_RIGHT);
335 menu.remove(ITextEditorActionConstants.SHIFT_LEFT);
336 menu.remove(ITextEditorActionConstants.CONTEXT_PREFERENCES);
337 }
338
339 @Override
340 public boolean canAttachMedia() {
341 return (getEditorInput() instanceof TaxonEditorInput || getEditorInput() instanceof OccurrenceEditorInput) ?true:false;
342 }
343
344 public IUndoContext getUndoContext() {
345 return undoContext;
346 }
347
348
349 }