ad3a5a6dc5215213121890cb138cfba834a1eeb2
[taxeditor.git] / taxeditor-editor / src / main / java / eu / etaxonomy / taxeditor / editor / name / NameViewer.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.editor.name;
11
12 import java.util.Iterator;
13
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;
47
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;
55
56 /**
57 * SourceViewer implementation called by NameComposite.
58 *
59 * @author p.ciardelli
60 * @created 27.05.2008
61 * @version 1.0
62 */
63 public class NameViewer extends SourceViewer {
64 private static final Logger logger = Logger
65 .getLogger(NameViewer.class);
66
67 /** Constant <code>RULER_WIDTH=16</code> */
68 public static final int RULER_WIDTH = 16;
69
70 private IVerticalRuler ruler;
71 private AnnotationModel annotationModel;
72
73 /**
74 * <p>Constructor for NameViewer.</p>
75 *
76 * @param parent a {@link org.eclipse.swt.widgets.Composite} object.
77 */
78 public NameViewer(Composite parent) {
79 super(parent, new RulerWithIcon(RULER_WIDTH), SWT.WRAP | SWT.MULTI | SWT.RESIZE);
80
81 this.ruler = getVerticalRuler();
82
83 setBackground(EditorUtil.getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
84
85 Canvas canvas = (Canvas) getControl();
86 TableWrapLayout layout = (TableWrapLayout) canvas.getLayout();
87 layout.topMargin = 0;
88 layout.rightMargin = 0;
89 layout.bottomMargin = 0;
90 layout.leftMargin = 0;
91 layout.verticalSpacing = 10;
92 layout.horizontalSpacing = 0;
93
94 canvas.setLayout(layout);
95
96 // Lay out the viewer's widgets
97 TableWrapData twdata = new TableWrapData(TableWrapData.FILL_GRAB);
98 getControl().setLayoutData(twdata);
99
100 twdata = new TableWrapData(TableWrapData.FILL_GRAB);
101 getTextWidget().setLayoutData(twdata);
102 getTextWidget().setLineSpacing(5);
103
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());
107
108 annotationModel = new AnnotationModel();
109 this.setDocument(new Document(""), annotationModel);
110
111 createAnnotationPainter();
112
113 this.configure(new ViewerConfiguration());
114
115 // setDecorationSupport();
116 // DocumentUndoManagerRegistry.connect(this.getDocument());
117 // IDocumentUndoManager docUndoManager = DocumentUndoManagerRegistry.getDocumentUndoManager(this.getDocument());
118
119 /**
120 getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.UNDO.getId(), new UndoActionHandler(getSite(), undoContext));
121 getEditorSite().getActionBars().setGlobalActionHandler(ActionFactory.REDO.getId(), new RedoActionHandler(getSite(), undoContext));
122 **/
123 }
124
125 /**
126 * <p>setBackground</p>
127 *
128 * @param color a {@link org.eclipse.swt.graphics.Color} object.
129 */
130 public void setBackground(Color color) {
131
132 // Set background color of ruler
133 ruler.getControl().setBackground(color);
134
135 // Set background color of text widget
136 getTextWidget().setBackground(color);
137
138 // Set background color of strip between ruler and textWidget
139 getTextWidget().getParent().setBackground(color);
140 }
141
142 /**
143 * <p>getRulerControl</p>
144 *
145 * @return a {@link org.eclipse.swt.widgets.Control} object.
146 */
147 public Control getRulerControl() {
148 return ruler.getControl();
149 }
150
151 /**
152 * <p>setIcon</p>
153 *
154 * @param icon a {@link org.eclipse.swt.graphics.Image} object.
155 */
156 public void setIcon(Image icon) {
157 if (ruler instanceof RulerWithIcon) {
158 ((RulerWithIcon) ruler).setIcon(icon);
159 } else {
160 logger.warn("Viewer's IVerticalRuler is not an instance of RulerWithIcon.");
161 }
162 }
163
164 /* (non-Javadoc)
165 * @see org.eclipse.jface.text.source.SourceViewer#createLayout()
166 */
167 /**
168 * <p>createLayout</p>
169 *
170 * @return a {@link org.eclipse.swt.widgets.Layout} object.
171 */
172 protected Layout createLayout() {
173 TableWrapLayout layout = new TableWrapLayout();
174 layout.numColumns = 2;
175 layout.verticalSpacing = 0;
176 return layout;
177 }
178
179 private void createAnnotationPainter(){
180 // Annotations section
181 IAnnotationAccess fAnnotationAccess = new DefaultMarkerAnnotationAccess();
182
183 // To paint the annotations
184 AnnotationPainter annotationPainter = new AnnotationPainter(this, fAnnotationAccess);
185
186 // Default SquigglesStrategy doesn't recognize line wraps
187 annotationPainter.addDrawingStrategy(LineWrapSquigglesStrategy.ID, new LineWrapSquigglesStrategy());
188
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));
193
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));
198
199 this.addPainter(annotationPainter);
200 }
201
202
203 /**
204 * <p>clearErrors</p>
205 */
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);
212 }
213 }
214 }
215
216 /**
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>.
220 *
221 * @param name a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase} object.
222 */
223 public void setShowParsingErrors(TaxonNameBase<?, ?> name) {
224
225 String text = this.getTextWidget().getText();
226
227 if (name.hasProblem() && text.length() > 0) {
228 int start = name.getProblemStarts();
229 int length = name.getProblemEnds() - start;
230
231 if (start == -1 || name.getProblemEnds() == -1) {
232 return;
233 }
234
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;
238 }
239
240 for (ParserProblem problem : name.getParsingProblems()) {
241
242 String type = null;
243 if (problem.isWarning()) {
244 type = EditorAnnotation.WARNING_TYPE;
245 }
246 if (problem.isError()) {
247 type = EditorAnnotation.ERROR_TYPE;
248 }
249 if (type == null) {
250 continue;
251 }
252 this.getAnnotationModel().addAnnotation(
253 new EditorAnnotation(type, 0, problem.getMessage()),
254 new Position(start, length));
255 }
256 }
257 }
258
259
260 /**
261 * <p>setShowSecError</p>
262 *
263 * @param taxon a {@link eu.etaxonomy.cdm.model.taxon.Taxon} object.
264 */
265 public void setShowSecError(Taxon taxon) {
266
267 // If taxon has no sec, show an annotation
268 if (taxon.getSec() == null) {
269
270 String text = "This taxon requires a sec. reference.";
271
272 this.getAnnotationModel().addAnnotation(
273 new EditorAnnotation(0, text),
274 new Position(0, 0));
275 }
276 }
277
278 public void setShowMultipleNameUsageWarning(TaxonNameBase name){
279 if(name.getTaxonBases().size() > 1){
280 String text = "This taxons name is used multiple times.";
281
282 this.getAnnotationModel().addAnnotation(
283 new EditorAnnotation(EditorAnnotation.WARNING_TYPE, 0, text),
284 new Position(0, 0));
285 }
286 }
287
288 /**
289 * @param name
290 */
291 public void setShowNameNotParsableWarning(NonViralName name) {
292 String text = "This name may only be edited in the details view.";
293
294 this.getAnnotationModel().addAnnotation(
295 new EditorAnnotation(EditorAnnotation.WARNING_TYPE, 0, text),
296 new Position(0, 0));
297
298 }
299
300 /**
301 * <p>setText</p>
302 *
303 * @param text a {@link java.lang.String} object.
304 */
305 public void setText(String text) {
306 if (text == null) {
307 text = "";
308 }
309 try {
310 Assert.isNotNull(text);
311 // TODO figure out why getTextWidget() returns null!
312 if (this.getTextWidget() == null) {
313 return;
314 }
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");
319 throw e;
320 }
321 }
322
323 /**
324 * <p>setMenu</p>
325 *
326 * @param menu a {@link org.eclipse.swt.widgets.Menu} object.
327 */
328 public void setMenu(Menu menu) {
329 getRulerControl().setMenu(menu);
330 getTextWidget().setMenu(menu);
331 }
332
333 /**
334 * <p>setCursorToEOL</p>
335 */
336 public void setCursorToEOL() {
337 getTextWidget().setCaretOffset(getTextWidget().getText().length());
338 getTextWidget().setFocus();
339 }
340
341
342 /**
343 * <p>getCursorPosition</p>
344 *
345 * @return a int.
346 */
347 public int getCursorPosition(){
348 return getTextWidget().getCaretOffset();
349 }
350
351 /**
352 * <p>setCursorPosition</p>
353 *
354 * @param offset a int.
355 */
356 public void setCursorPosition(int offset){
357 try{
358 getTextWidget().setCaretOffset(offset);
359 }catch(IllegalArgumentException e){
360 // do nothing
361 }
362 }
363
364 /**
365 * <p>createUndoSupport</p>
366 *
367 * @param editorSite a {@link org.eclipse.ui.IEditorSite} object.
368 */
369 public void createUndoSupport(IEditorSite editorSite) {
370
371 IUndoManager undoManager = new TextViewerUndoManager(25);
372 this.setUndoManager(undoManager);
373 undoManager.connect(this);
374
375 // IUndoContext workbenchUndoContext = UiUtil.getWorkbenchUndoContext();
376
377 IUndoContext workbenchUndoContext = ((IUndoManagerExtension)undoManager).getUndoContext();
378
379 OperationHistoryActionHandler undoAction = new UndoActionHandler(editorSite, workbenchUndoContext);
380 // undoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
381 undoAction.setActionDefinitionId(ActionFactory.UNDO.getId());
382
383 // Create the redo action.
384 OperationHistoryActionHandler redoAction = new RedoActionHandler(editorSite, workbenchUndoContext);
385 // redoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO);
386 undoAction.setActionDefinitionId(ActionFactory.REDO.getId());
387
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);
394
395 }
396
397 // actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(), undoAction);
398 // actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(), redoAction);
399 }
400
401 /**
402 * <p>createUndoSupport_</p>
403 *
404 * @param editorSite a {@link org.eclipse.ui.IEditorSite} object.
405 */
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();
413
414 OperationHistoryActionHandler undoAction = new UndoActionHandler(editorSite, undoContext);
415 // PlatformUI.getWorkbench().getHelpSystem().setHelp(undoAction, IAbstractTextEditorHelpContextIds.UNDO_ACTION);
416 undoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
417
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);
422
423
424 IActionBars actionBars = editorSite.getActionBars();
425 if (actionBars != null) {
426 actionBars.setGlobalActionHandler(IWorkbenchActionDefinitionIds.UNDO, undoAction);
427 actionBars.setGlobalActionHandler(IWorkbenchActionDefinitionIds.REDO, redoAction);
428
429 }
430 }
431 }
432
433 }
434