3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
11 package eu
.etaxonomy
.taxeditor
.bulkeditor
;
13 import java
.beans
.PropertyChangeEvent
;
14 import java
.beans
.PropertyChangeListener
;
15 import java
.util
.Iterator
;
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
;
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
;
54 * <p>BulkEditor class.</p>
60 public class BulkEditor
extends AnnotatedLineEditor
implements PropertyChangeListener
, IPartContentHasDetails
, IDirtyMarkableSelectionProvider
{
62 /** Constant <code>ID="bulkeditor.editor"</code> */
63 public static final String ID
= "bulkeditor.editor";
65 private boolean isInitialFocus
= true;
67 private BulkEditorSearchComposite searchBar
= null;
69 private IPropertyChangeListener markerPreferenceListener
;
72 * <p>Constructor for BulkEditor.</p>
75 super(CdmStore
.createConversation());
79 * @see org.eclipse.ui.editors.text.TextEditor#initializeEditor()
83 protected void initializeEditor() {
84 super.initializeEditor();
87 * see AbstractTextEditor javadoc for explanation of context menu ids
89 setEditorContextMenuId("#BulkEditorContext");
91 setEntityCreatorService(new BulkEditorEntityCreatorService());
93 setLineDisplayStrategy(new BulkEditorLineDisplay(this));
95 setSourceViewerConfiguration(new BulkEditorViewerConfiguration(lineDisplayStrategy
));
99 * @see eu.etaxonomy.taxeditor.bulkeditor.ListEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, org.eclipse.jface.text.source.IVerticalRuler, int)
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());
112 * @see eu.etaxonomy.taxeditor.bulkeditor.AnnotatedLineEditor#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
116 public void init(IEditorSite site
, IEditorInput input
)
117 throws PartInitException
{
119 if (!(input
instanceof AbstractBulkEditorInput
)) {
120 throw new PartInitException("Invalid Input: Must be BulkEditorInput");
123 super.init(site
, input
);
125 ((AbstractBulkEditorInput
) input
).addPropertyChangeListener(this);
129 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite)
133 public void createPartControl(Composite parent
) {
135 parent
.setLayout(new GridLayout());
137 Composite layoutComposite
= new Composite(parent
, SWT
.TOP
);
138 layoutComposite
.setLayout(new GridLayout());
140 searchBar
= new BulkEditorSearchComposite(this, layoutComposite
, SWT
.NONE
);
141 layoutComposite
.setBackground(parent
.getDisplay().getSystemColor(SWT
.COLOR_WIDGET_BACKGROUND
));
143 if (isEditableMarkerTypes()) {
144 // TODO this will be obsolete
145 // createMarkerEditing(layoutComposite);
148 searchBar
.setEnabled(! getEditorInput().isSingleEntityMode());
150 super.createPartControl(parent
);
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));
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();
176 PreferencesUtil
.getPreferenceStore().addPropertyChangeListener(markerPreferenceListener
);
180 * @see org.eclipse.ui.editors.text.TextEditor#dispose()
184 public void dispose() {
185 if (markerPreferenceListener
!= null ) {
186 PreferencesUtil
.getPreferenceStore().removePropertyChangeListener(markerPreferenceListener
);
192 * Can this input type edit any markers?
196 private boolean isEditableMarkerTypes() {
197 for (MarkerType markerType
: TermStore
.getNonTechnicalMarkerTypes()) {
198 if (((AbstractBulkEditorInput
) getEditorInput()).isMarkerTypeEditingEnabled(markerType
)) {
206 * Refreshes text in all lines.
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
);
224 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#isEditable()
228 public boolean isEditable() {
233 * @see eu.etaxonomy.taxeditor.annotatedlineeditor.AnnotatedLineEditor#setFocus()
237 public void setFocus() {
240 // TODO Since setFocus() is called by RCP, can a global variable (searchBar) be avoided?
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;
252 * Sets focus on the toolbar.
254 private void setFocusOnToolBar() {
255 if (searchBar
!= null) {
256 searchBar
.setFocus();
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());
281 private void addToggleMergeCandidateListener(Control control
) {
282 control
.addMouseListener(new MouseAdapter() {
284 public void mouseDoubleClick(MouseEvent e
) {
285 StyledText textWidget
= getSourceViewer().getTextWidget();
286 int line
= textWidget
.getLineIndex(e
.y
);
287 toggleMergeCandidateAnnotation(line
);
293 * <p>toggleMergeCandidateAnnotation</p>
297 public void toggleMergeCandidateAnnotation(int line
) {
299 IDocument document
= getSourceViewer().getDocument();
300 LineAnnotationModel model
=
301 (LineAnnotationModel
) getSourceViewer().getAnnotationModel();
303 Annotation annotation
= model
.getAnnotationAtLine(line
, document
);
305 if (annotation
!= null) {
306 if (annotation
.getType().equals(IBulkEditorConstants
.TYPE_MERGE_CANDIDATE
)) {
307 model
.changeAnnotationType(
308 annotation
, LineAnnotation
.TYPE_GENERIC
);
310 model
.changeAnnotationType(
311 annotation
, IBulkEditorConstants
.TYPE_MERGE_CANDIDATE
);
317 public void changed(Object object
) {
318 // this.dirty = dirty;
319 AnnotatedLineDocumentProvider p
= (AnnotatedLineDocumentProvider
) getDocumentProvider();
321 // firePropertyChange(PROP_DIRTY);
325 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
328 public void propertyChange(PropertyChangeEvent evt
) {
329 if (evt
.getPropertyName().equals(AbstractBulkEditorInput
.QUERY_CHANGED
)) {
331 // TODO check if dirty, prompt save
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?");
341 if(getDocumentProvider().getAnnotationModel(getEditorInput()) != null){
342 ((AnnotationModel
) getDocumentProvider().getAnnotationModel(getEditorInput())).removeAllAnnotations();
344 setInput(getEditorInput());
349 * @see org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor#getContributorId()
352 * <p>getContributorId</p>
354 * @return a {@link java.lang.String} object.
356 public String
getContributorId() {
357 return BulkEditor
.ID
;
362 public AbstractBulkEditorInput
getEditorInput() {
363 // TODO Auto-generated method stub
364 return (AbstractBulkEditorInput
) super.getEditorInput();