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