2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.taxeditor
.editor
.name
;
12 import java
.util
.Iterator
;
14 import org
.apache
.log4j
.Logger
;
15 import org
.eclipse
.core
.commands
.operations
.IUndoContext
;
16 import org
.eclipse
.core
.runtime
.Assert
;
17 import org
.eclipse
.jface
.text
.Document
;
18 import org
.eclipse
.jface
.text
.IUndoManager
;
19 import org
.eclipse
.jface
.text
.IUndoManagerExtension
;
20 import org
.eclipse
.jface
.text
.Position
;
21 import org
.eclipse
.jface
.text
.TextViewerUndoManager
;
22 import org
.eclipse
.jface
.text
.source
.Annotation
;
23 import org
.eclipse
.jface
.text
.source
.AnnotationModel
;
24 import org
.eclipse
.jface
.text
.source
.AnnotationPainter
;
25 import org
.eclipse
.jface
.text
.source
.IAnnotationAccess
;
26 import org
.eclipse
.jface
.text
.source
.IVerticalRuler
;
27 import org
.eclipse
.jface
.text
.source
.SourceViewer
;
28 import org
.eclipse
.swt
.SWT
;
29 import org
.eclipse
.swt
.graphics
.Color
;
30 import org
.eclipse
.swt
.graphics
.Image
;
31 import org
.eclipse
.swt
.widgets
.Canvas
;
32 import org
.eclipse
.swt
.widgets
.Composite
;
33 import org
.eclipse
.swt
.widgets
.Control
;
34 import org
.eclipse
.swt
.widgets
.Display
;
35 import org
.eclipse
.swt
.widgets
.Layout
;
36 import org
.eclipse
.swt
.widgets
.Menu
;
37 import org
.eclipse
.ui
.IActionBars
;
38 import org
.eclipse
.ui
.IEditorSite
;
39 import org
.eclipse
.ui
.actions
.ActionFactory
;
40 import org
.eclipse
.ui
.forms
.widgets
.TableWrapData
;
41 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
42 import org
.eclipse
.ui
.operations
.OperationHistoryActionHandler
;
43 import org
.eclipse
.ui
.operations
.RedoActionHandler
;
44 import org
.eclipse
.ui
.operations
.UndoActionHandler
;
45 import org
.eclipse
.ui
.texteditor
.DefaultMarkerAnnotationAccess
;
46 import org
.eclipse
.ui
.texteditor
.IWorkbenchActionDefinitionIds
;
48 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
49 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
50 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
51 import eu
.etaxonomy
.cdm
.strategy
.parser
.ParserProblem
;
52 import eu
.etaxonomy
.taxeditor
.editor
.EditorUtil
;
53 import eu
.etaxonomy
.taxeditor
.editor
.ViewerConfiguration
;
54 import eu
.etaxonomy
.taxeditor
.preference
.Resources
;
57 * SourceViewer implementation called by NameComposite.
63 public class NameViewer
extends SourceViewer
{
64 private static final Logger logger
= Logger
65 .getLogger(NameViewer
.class);
67 /** Constant <code>RULER_WIDTH=16</code> */
68 public static final int RULER_WIDTH
= 16;
70 private IVerticalRuler ruler
;
71 private AnnotationModel annotationModel
;
74 * <p>Constructor for NameViewer.</p>
76 * @param parent a {@link org.eclipse.swt.widgets.Composite} object.
78 public NameViewer(Composite parent
) {
79 super(parent
, new RulerWithIcon(RULER_WIDTH
), SWT
.WRAP
| SWT
.MULTI
| SWT
.RESIZE
);
81 this.ruler
= getVerticalRuler();
83 setBackground(EditorUtil
.getColor(Resources
.COLOR_COMPOSITE_BACKGROUND
));
85 Canvas canvas
= (Canvas
) getControl();
86 TableWrapLayout layout
= (TableWrapLayout
) canvas
.getLayout();
88 layout
.rightMargin
= 0;
89 layout
.bottomMargin
= 0;
90 layout
.leftMargin
= 0;
91 layout
.verticalSpacing
= 10;
92 layout
.horizontalSpacing
= 0;
94 canvas
.setLayout(layout
);
96 // Lay out the viewer's widgets
97 TableWrapData twdata
= new TableWrapData(TableWrapData
.FILL_GRAB
);
98 getControl().setLayoutData(twdata
);
100 twdata
= new TableWrapData(TableWrapData
.FILL_GRAB
);
101 getTextWidget().setLayoutData(twdata
);
102 getTextWidget().setLineSpacing(5);
104 // Default implementation adds ruler after the text widget, then
105 // uses a custom layout to display it before the text widget
106 ruler
.getControl().moveAbove(getTextWidget());
108 annotationModel
= new AnnotationModel();
109 this.setDocument(new Document(""), annotationModel
);
111 createAnnotationPainter();
113 this.configure(new ViewerConfiguration());
115 // setDecorationSupport();
116 // DocumentUndoManagerRegistry.connect(this.getDocument());
117 // IDocumentUndoManager docUndoManager = DocumentUndoManagerRegistry.getDocumentUndoManager(this.getDocument());
120 getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.UNDO.getId(), new UndoActionHandler(getSite(), undoContext));
121 getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.REDO.getId(), new RedoActionHandler(getSite(), undoContext));
126 * <p>setBackground</p>
128 * @param color a {@link org.eclipse.swt.graphics.Color} object.
130 public void setBackground(Color color
) {
132 // Set background color of ruler
133 ruler
.getControl().setBackground(color
);
135 // Set background color of text widget
136 getTextWidget().setBackground(color
);
138 // Set background color of strip between ruler and textWidget
139 getTextWidget().getParent().setBackground(color
);
143 * <p>getRulerControl</p>
145 * @return a {@link org.eclipse.swt.widgets.Control} object.
147 public Control
getRulerControl() {
148 return ruler
.getControl();
154 * @param icon a {@link org.eclipse.swt.graphics.Image} object.
156 public void setIcon(Image icon
) {
157 if (ruler
instanceof RulerWithIcon
) {
158 ((RulerWithIcon
) ruler
).setIcon(icon
);
160 logger
.warn("Viewer's IVerticalRuler is not an instance of RulerWithIcon.");
165 * @see org.eclipse.jface.text.source.SourceViewer#createLayout()
168 * <p>createLayout</p>
170 * @return a {@link org.eclipse.swt.widgets.Layout} object.
172 protected Layout
createLayout() {
173 TableWrapLayout layout
= new TableWrapLayout();
174 layout
.numColumns
= 2;
175 layout
.verticalSpacing
= 0;
179 private void createAnnotationPainter(){
180 // Annotations section
181 IAnnotationAccess fAnnotationAccess
= new DefaultMarkerAnnotationAccess();
183 // To paint the annotations
184 AnnotationPainter annotationPainter
= new AnnotationPainter(this, fAnnotationAccess
);
186 // Default SquigglesStrategy doesn't recognize line wraps
187 annotationPainter
.addDrawingStrategy(LineWrapSquigglesStrategy
.ID
, new LineWrapSquigglesStrategy());
189 // Add ability to paint red squigglies
190 annotationPainter
.addAnnotationType(EditorAnnotation
.ERROR_TYPE
, LineWrapSquigglesStrategy
.ID
);
191 annotationPainter
.setAnnotationTypeColor(EditorAnnotation
.ERROR_TYPE
,
192 new Color(Display
.getDefault(), EditorAnnotation
.ERROR_RGB
));
194 // Add ability to paint yellow squigglies
195 annotationPainter
.addAnnotationType(EditorAnnotation
.WARNING_TYPE
, LineWrapSquigglesStrategy
.ID
);
196 annotationPainter
.setAnnotationTypeColor(EditorAnnotation
.WARNING_TYPE
,
197 new Color(Display
.getDefault(), EditorAnnotation
.WARNING_RGB
));
199 this.addPainter(annotationPainter
);
206 public void clearErrors() {
207 Iterator
<Annotation
> annotations
= this.getAnnotationModel().getAnnotationIterator();
208 while (annotations
.hasNext()) {
209 Annotation annotation
= annotations
.next();
210 if (annotation
.getType().equals(EditorAnnotation
.ERROR_TYPE
) || annotation
.getType().equals(EditorAnnotation
.WARNING_TYPE
)) {
211 this.getAnnotationModel().removeAnnotation(annotation
);
217 * If <code>name.hasProblem()</code> is <code>true</code>, underlines section
218 * of text bounded by <code>name.getProblemStarts()</code> and
219 * <code>name.getProblemEnds()</code>.
221 * @param name a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
223 public void setShowParsingErrors(TaxonNameBase
<?
, ?
> name
) {
225 String text
= this.getTextWidget().getText();
227 if (name
.hasProblem() && text
.length() > 0) {
228 int start
= name
.getProblemStarts();
229 int length
= name
.getProblemEnds() - start
;
231 if (start
== -1 || name
.getProblemEnds() == -1) {
235 // Don't let squigglies try to draw beyond the end of the text
236 if (text
.length() < start
+ length
) {
237 length
= text
.length() - start
;
240 for (ParserProblem problem
: name
.getParsingProblems()) {
243 if (problem
.isWarning()) {
244 type
= EditorAnnotation
.WARNING_TYPE
;
246 if (problem
.isError()) {
247 type
= EditorAnnotation
.ERROR_TYPE
;
252 this.getAnnotationModel().addAnnotation(
253 new EditorAnnotation(type
, 0, problem
.getMessage()),
254 new Position(start
, length
));
261 * <p>setShowSecError</p>
263 * @param taxon a {@link eu.etaxonomy.cdm.model.taxon.Taxon} object.
265 public void setShowSecError(Taxon taxon
) {
267 // If taxon has no sec, show an annotation
268 if (taxon
.getSec() == null) {
270 String text
= "This taxon requires a sec. reference.";
272 this.getAnnotationModel().addAnnotation(
273 new EditorAnnotation(0, text
),
278 public void setShowMultipleNameUsageWarning(TaxonNameBase name
){
279 if(name
.getTaxonBases().size() > 1){
280 String text
= "This taxons name is used multiple times.";
282 this.getAnnotationModel().addAnnotation(
283 new EditorAnnotation(EditorAnnotation
.WARNING_TYPE
, 0, text
),
291 public void setShowNameNotParsableWarning(NonViralName name
) {
292 String text
= "This name may only be edited in the details view.";
294 this.getAnnotationModel().addAnnotation(
295 new EditorAnnotation(EditorAnnotation
.WARNING_TYPE
, 0, text
),
303 * @param text a {@link java.lang.String} object.
305 public void setText(String text
) {
310 Assert
.isNotNull(text
);
311 // TODO figure out why getTextWidget() returns null!
312 if (this.getTextWidget() == null) {
315 Assert
.isNotNull(this.getTextWidget());
316 this.getTextWidget().setText(text
);
317 } catch (RuntimeException e
) {
318 logger
.error("Could not set the text for a name viewer");
326 * @param menu a {@link org.eclipse.swt.widgets.Menu} object.
328 public void setMenu(Menu menu
) {
329 getRulerControl().setMenu(menu
);
330 getTextWidget().setMenu(menu
);
334 * <p>setCursorToEOL</p>
336 public void setCursorToEOL() {
337 getTextWidget().setCaretOffset(getTextWidget().getText().length());
338 getTextWidget().setFocus();
343 * <p>getCursorPosition</p>
347 public int getCursorPosition(){
348 return getTextWidget().getCaretOffset();
352 * <p>setCursorPosition</p>
354 * @param offset a int.
356 public void setCursorPosition(int offset
){
358 getTextWidget().setCaretOffset(offset
);
359 }catch(IllegalArgumentException e
){
365 * <p>createUndoSupport</p>
367 * @param editorSite a {@link org.eclipse.ui.IEditorSite} object.
369 public void createUndoSupport(IEditorSite editorSite
) {
371 IUndoManager undoManager
= new TextViewerUndoManager(25);
372 this.setUndoManager(undoManager
);
373 undoManager
.connect(this);
375 // IUndoContext workbenchUndoContext = UiUtil.getWorkbenchUndoContext();
377 IUndoContext workbenchUndoContext
= ((IUndoManagerExtension
)undoManager
).getUndoContext();
379 OperationHistoryActionHandler undoAction
= new UndoActionHandler(editorSite
, workbenchUndoContext
);
380 // undoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
381 undoAction
.setActionDefinitionId(ActionFactory
.UNDO
.getId());
383 // Create the redo action.
384 OperationHistoryActionHandler redoAction
= new RedoActionHandler(editorSite
, workbenchUndoContext
);
385 // redoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO);
386 undoAction
.setActionDefinitionId(ActionFactory
.REDO
.getId());
388 IActionBars actionBars
= editorSite
.getActionBars();
389 if (actionBars
!= null) {
390 // actionBars.setGlobalActionHandler(IWorkbenchActionDefinitionIds.UNDO, undoAction);
391 // actionBars.setGlobalActionHandler(IWorkbenchActionDefinitionIds.REDO, redoAction);
392 actionBars
.setGlobalActionHandler(ActionFactory
.UNDO
.getId(), undoAction
);
393 actionBars
.setGlobalActionHandler(ActionFactory
.REDO
.getId(), redoAction
);
397 // actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undoAction);
398 // actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), redoAction);
402 * <p>createUndoSupport_</p>
404 * @param editorSite a {@link org.eclipse.ui.IEditorSite} object.
406 public void createUndoSupport_(IEditorSite editorSite
) {
407 IUndoManager undoManager
= new TextViewerUndoManager(25);
408 this.setUndoManager(undoManager
);
409 undoManager
.connect(this);
410 IUndoContext undoContext
;
411 if (undoManager
instanceof IUndoManagerExtension
) {
412 undoContext
= ((IUndoManagerExtension
)undoManager
).getUndoContext();
414 OperationHistoryActionHandler undoAction
= new UndoActionHandler(editorSite
, undoContext
);
415 // PlatformUI.getWorkbench().getHelpSystem().setHelp(undoAction, IAbstractTextEditorHelpContextIds.UNDO_ACTION);
416 undoAction
.setActionDefinitionId(IWorkbenchActionDefinitionIds
.UNDO
);
418 // Create the redo action.
419 OperationHistoryActionHandler redoAction
= new RedoActionHandler(editorSite
, undoContext
);
420 // PlatformUI.getWorkbench().getHelpSystem().setHelp(redoAction, IAbstractTextEditorHelpContextIds.REDO_ACTION);
421 redoAction
.setActionDefinitionId(IWorkbenchActionDefinitionIds
.REDO
);
424 IActionBars actionBars
= editorSite
.getActionBars();
425 if (actionBars
!= null) {
426 actionBars
.setGlobalActionHandler(IWorkbenchActionDefinitionIds
.UNDO
, undoAction
);
427 actionBars
.setGlobalActionHandler(IWorkbenchActionDefinitionIds
.REDO
, redoAction
);