comparison dwtx/jface/text/source/SourceViewer.d @ 129:eb30df5ca28b

Added JFace Text sources
author Frank Benoit <benoit@tionex.de>
date Sat, 23 Aug 2008 19:10:48 +0200
parents
children c4fb132a086c
comparison
equal deleted inserted replaced
128:8df1d4193877 129:eb30df5ca28b
1 /*******************************************************************************
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module dwtx.jface.text.source.SourceViewer;
14
15 import dwt.dwthelper.utils;
16
17 import java.util.Iterator;
18 import java.util.Stack;
19
20 import dwt.DWT;
21 import dwt.graphics.Point;
22 import dwt.graphics.Rectangle;
23 import dwt.widgets.Canvas;
24 import dwt.widgets.Composite;
25 import dwt.widgets.Control;
26 import dwt.widgets.Layout;
27 import dwtx.jface.internal.text.NonDeletingPositionUpdater;
28 import dwtx.jface.internal.text.StickyHoverManager;
29 import dwtx.jface.text.AbstractHoverInformationControlManager;
30 import dwtx.jface.text.BadLocationException;
31 import dwtx.jface.text.BadPositionCategoryException;
32 import dwtx.jface.text.DocumentRewriteSession;
33 import dwtx.jface.text.DocumentRewriteSessionType;
34 import dwtx.jface.text.IDocument;
35 import dwtx.jface.text.IDocumentExtension4;
36 import dwtx.jface.text.IPositionUpdater;
37 import dwtx.jface.text.IRegion;
38 import dwtx.jface.text.IRewriteTarget;
39 import dwtx.jface.text.ISlaveDocumentManager;
40 import dwtx.jface.text.ISlaveDocumentManagerExtension;
41 import dwtx.jface.text.ITextViewerExtension2;
42 import dwtx.jface.text.Position;
43 import dwtx.jface.text.Region;
44 import dwtx.jface.text.TextViewer;
45 import dwtx.jface.text.contentassist.IContentAssistant;
46 import dwtx.jface.text.contentassist.IContentAssistantExtension4;
47 import dwtx.jface.text.formatter.FormattingContext;
48 import dwtx.jface.text.formatter.FormattingContextProperties;
49 import dwtx.jface.text.formatter.IContentFormatter;
50 import dwtx.jface.text.formatter.IContentFormatterExtension;
51 import dwtx.jface.text.formatter.IFormattingContext;
52 import dwtx.jface.text.hyperlink.IHyperlinkDetector;
53 import dwtx.jface.text.information.IInformationPresenter;
54 import dwtx.jface.text.presentation.IPresentationReconciler;
55 import dwtx.jface.text.projection.ChildDocument;
56 import dwtx.jface.text.quickassist.IQuickAssistAssistant;
57 import dwtx.jface.text.quickassist.IQuickAssistInvocationContext;
58 import dwtx.jface.text.reconciler.IReconciler;
59
60 /**
61 * DWT based implementation of
62 * {@link dwtx.jface.text.source.ISourceViewer} and its extension
63 * interfaces. The same rules apply as for
64 * {@link dwtx.jface.text.TextViewer}. A source viewer uses an
65 * <code>IVerticalRuler</code> as its annotation presentation area. The
66 * vertical ruler is a small strip shown left of the viewer's text widget. A
67 * source viewer uses an <code>IOverviewRuler</code> as its presentation area
68 * for the annotation overview. The overview ruler is a small strip shown right
69 * of the viewer's text widget.
70 * <p>
71 * Clients are supposed to instantiate a source viewer and subsequently to
72 * communicate with it exclusively using the <code>ISourceViewer</code> and
73 * its extension interfaces.</p>
74 * <p>
75 * Clients may subclass this class but should expect some breakage by future releases.</p>
76 */
77 public class SourceViewer : TextViewer , ISourceViewer, ISourceViewerExtension, ISourceViewerExtension2, ISourceViewerExtension3, ISourceViewerExtension4 {
78
79
80 /**
81 * Layout of a source viewer. Vertical ruler, text widget, and overview ruler are shown side by side.
82 */
83 protected class RulerLayout : Layout {
84
85 /** The gap between the text viewer and the vertical ruler. */
86 protected int fGap;
87
88 /**
89 * Creates a new ruler layout with the given gap between text viewer and vertical ruler.
90 *
91 * @param gap the gap between text viewer and vertical ruler
92 */
93 public RulerLayout(int gap) {
94 fGap= gap;
95 }
96
97 /*
98 * @see Layout#computeSize(Composite, int, int, bool)
99 */
100 protected Point computeSize(Composite composite, int wHint, int hHint, bool flushCache) {
101 Control[] children= composite.getChildren();
102 Point s= children[children.length - 1].computeSize(DWT.DEFAULT, DWT.DEFAULT, flushCache);
103 if (fVerticalRuler !is null && fIsVerticalRulerVisible)
104 s.x += fVerticalRuler.getWidth() + fGap;
105 return s;
106 }
107
108 /*
109 * @see Layout#layout(Composite, bool)
110 */
111 protected void layout(Composite composite, bool flushCache) {
112 Rectangle clArea= composite.getClientArea();
113 Rectangle trim= getTextWidget().computeTrim(0, 0, 0, 0);
114 int topTrim= - trim.y;
115 int scrollbarHeight= trim.height - topTrim; // scrollbar is only under the client area
116
117 int x= clArea.x;
118 int width= clArea.width;
119
120 if (fOverviewRuler !is null && fIsOverviewRulerVisible) {
121 int overviewRulerWidth= fOverviewRuler.getWidth();
122 fOverviewRuler.getControl().setBounds(clArea.x + clArea.width - overviewRulerWidth - 1, clArea.y + scrollbarHeight, overviewRulerWidth, clArea.height - 3*scrollbarHeight);
123 fOverviewRuler.getHeaderControl().setBounds(clArea.x + clArea.width - overviewRulerWidth - 1, clArea.y, overviewRulerWidth, scrollbarHeight);
124
125 width -= overviewRulerWidth + fGap;
126 }
127
128 if (fVerticalRuler !is null && fIsVerticalRulerVisible) {
129 int verticalRulerWidth= fVerticalRuler.getWidth();
130 final Control verticalRulerControl= fVerticalRuler.getControl();
131 int oldWidth= verticalRulerControl.getBounds().width;
132 verticalRulerControl.setBounds(clArea.x, clArea.y + topTrim, verticalRulerWidth, clArea.height - scrollbarHeight - topTrim);
133 if (flushCache && getVisualAnnotationModel() !is null && oldWidth is verticalRulerWidth)
134 verticalRulerControl.redraw();
135
136 x += verticalRulerWidth + fGap;
137 width -= verticalRulerWidth + fGap;
138 }
139
140 getTextWidget().setBounds(x, clArea.y, width, clArea.height);
141 }
142 }
143
144 /**
145 * The size of the gap between the vertical ruler and the text widget
146 * (value <code>2</code>).
147 * <p>
148 * Note: As of 3.2, the text editor framework is no longer using 2 as
149 * gap but 1, see {{@link #GAP_SIZE_1 }.
150 * </p>
151 */
152 protected final static int GAP_SIZE= 2;
153 /**
154 * The size of the gap between the vertical ruler and the text widget
155 * (value <code>1</code>).
156 * @since 3.2
157 */
158 protected final static int GAP_SIZE_1= 1;
159 /**
160 * Partial name of the position category to manage remembered selections.
161 * @since 3.0
162 */
163 protected final static String _SELECTION_POSITION_CATEGORY= "__selection_category"; //$NON-NLS-1$
164 /**
165 * Key of the model annotation model inside the visual annotation model.
166 * @since 3.0
167 */
168 protected final static Object MODEL_ANNOTATION_MODEL= new Object();
169
170 /** The viewer's content assistant */
171 protected IContentAssistant fContentAssistant;
172 /**
173 * The viewer's facade to its content assistant.
174 * @since 3.4
175 */
176 private ContentAssistantFacade fContentAssistantFacade;
177 /**
178 * Flag indicating whether the viewer's content assistant is installed.
179 * @since 2.0
180 */
181 protected bool fContentAssistantInstalled;
182 /**
183 * This viewer's quick assist assistant.
184 * @since 3.2
185 */
186 protected IQuickAssistAssistant fQuickAssistAssistant;
187 /**
188 * Flag indicating whether this viewer's quick assist assistant is installed.
189 * @since 3.2
190 */
191 protected bool fQuickAssistAssistantInstalled;
192 /** The viewer's content formatter */
193 protected IContentFormatter fContentFormatter;
194 /** The viewer's model reconciler */
195 protected IReconciler fReconciler;
196 /** The viewer's presentation reconciler */
197 protected IPresentationReconciler fPresentationReconciler;
198 /** The viewer's annotation hover */
199 protected IAnnotationHover fAnnotationHover;
200 /**
201 * Stack of saved selections in the underlying document
202 * @since 3.0
203 */
204 protected final Stack fSelections= new Stack();
205 /**
206 * Position updater for saved selections
207 * @since 3.0
208 */
209 protected IPositionUpdater fSelectionUpdater= null;
210 /**
211 * Position category used by the selection updater
212 * @since 3.0
213 */
214 protected String fSelectionCategory;
215 /**
216 * The viewer's overview ruler annotation hover
217 * @since 3.0
218 */
219 protected IAnnotationHover fOverviewRulerAnnotationHover;
220 /**
221 * The viewer's information presenter
222 * @since 2.0
223 */
224 protected IInformationPresenter fInformationPresenter;
225
226 /** Visual vertical ruler */
227 private IVerticalRuler fVerticalRuler;
228 /** Visibility of vertical ruler */
229 private bool fIsVerticalRulerVisible;
230 /** The DWT widget used when supporting a vertical ruler */
231 private Composite fComposite;
232 /** The vertical ruler's annotation model */
233 private IAnnotationModel fVisualAnnotationModel;
234 /** The viewer's range indicator to be shown in the vertical ruler */
235 private Annotation fRangeIndicator;
236 /** The viewer's vertical ruler hovering controller */
237 private AnnotationBarHoverManager fVerticalRulerHoveringController;
238 /**
239 * The viewer's overview ruler hovering controller
240 * @since 2.1
241 */
242 private AbstractHoverInformationControlManager fOverviewRulerHoveringController;
243
244 /**
245 * The overview ruler.
246 * @since 2.1
247 */
248 private IOverviewRuler fOverviewRuler;
249 /**
250 * The visibility of the overview ruler
251 * @since 2.1
252 */
253 private bool fIsOverviewRulerVisible;
254
255
256 /**
257 * Constructs a new source viewer. The vertical ruler is initially visible.
258 * The viewer has not yet been initialized with a source viewer configuration.
259 *
260 * @param parent the parent of the viewer's control
261 * @param ruler the vertical ruler used by this source viewer
262 * @param styles the DWT style bits for the viewer's control,
263 * <em>if <code>DWT.WRAP</code> is set then a custom document adapter needs to be provided, see {@link #createDocumentAdapter()}
264 */
265 public SourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
266 this(parent, ruler, null, false, styles);
267 }
268
269 /**
270 * Constructs a new source viewer. The vertical ruler is initially visible.
271 * The overview ruler visibility is controlled by the value of <code>showAnnotationsOverview</code>.
272 * The viewer has not yet been initialized with a source viewer configuration.
273 *
274 * @param parent the parent of the viewer's control
275 * @param verticalRuler the vertical ruler used by this source viewer
276 * @param overviewRuler the overview ruler
277 * @param showAnnotationsOverview <code>true</code> if the overview ruler should be visible, <code>false</code> otherwise
278 * @param styles the DWT style bits for the viewer's control,
279 * <em>if <code>DWT.WRAP</code> is set then a custom document adapter needs to be provided, see {@link #createDocumentAdapter()}
280 * @since 2.1
281 */
282 public SourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, bool showAnnotationsOverview, int styles) {
283 super();
284
285 fVerticalRuler= verticalRuler;
286 fIsVerticalRulerVisible= (verticalRuler !is null);
287 fOverviewRuler= overviewRuler;
288 fIsOverviewRulerVisible= (showAnnotationsOverview && overviewRuler !is null);
289
290 createControl(parent, styles);
291 }
292
293 /*
294 * @see TextViewer#createControl(Composite, int)
295 */
296 protected void createControl(Composite parent, int styles) {
297
298 if (fVerticalRuler !is null || fOverviewRuler !is null) {
299 styles= (styles & ~DWT.BORDER);
300 fComposite= new Canvas(parent, DWT.NONE);
301 fComposite.setLayout(createLayout());
302 parent= fComposite;
303 }
304
305 super.createControl(parent, styles);
306
307 if (fVerticalRuler !is null)
308 fVerticalRuler.createControl(fComposite, this);
309 if (fOverviewRuler !is null)
310 fOverviewRuler.createControl(fComposite, this);
311 }
312
313 /**
314 * Creates the layout used for this viewer.
315 * Subclasses may override this method.
316 *
317 * @return the layout used for this viewer
318 * @since 3.0
319 */
320 protected Layout createLayout() {
321 return new RulerLayout(GAP_SIZE_1);
322 }
323
324 /*
325 * @see TextViewer#getControl()
326 */
327 public Control getControl() {
328 if (fComposite !is null)
329 return fComposite;
330 return super.getControl();
331 }
332
333 /*
334 * @see ISourceViewer#setAnnotationHover(IAnnotationHover)
335 */
336 public void setAnnotationHover(IAnnotationHover annotationHover) {
337 fAnnotationHover= annotationHover;
338 }
339
340 /**
341 * Sets the overview ruler's annotation hover of this source viewer.
342 * The annotation hover provides the information to be displayed in a hover
343 * popup window if requested over the overview rulers area. The annotation
344 * hover is assumed to be line oriented.
345 *
346 * @param annotationHover the hover to be used, <code>null</code> is a valid argument
347 * @since 3.0
348 */
349 public void setOverviewRulerAnnotationHover(IAnnotationHover annotationHover) {
350 fOverviewRulerAnnotationHover= annotationHover;
351 }
352
353 /*
354 * @see ISourceViewer#configure(SourceViewerConfiguration)
355 */
356 public void configure(SourceViewerConfiguration configuration) {
357
358 if (getTextWidget() is null)
359 return;
360
361 setDocumentPartitioning(configuration.getConfiguredDocumentPartitioning(this));
362
363 // install content type independent plug-ins
364 fPresentationReconciler= configuration.getPresentationReconciler(this);
365 if (fPresentationReconciler !is null)
366 fPresentationReconciler.install(this);
367
368 fReconciler= configuration.getReconciler(this);
369 if (fReconciler !is null)
370 fReconciler.install(this);
371
372 fContentAssistant= configuration.getContentAssistant(this);
373 if (fContentAssistant !is null) {
374 fContentAssistant.install(this);
375 if (fContentAssistant instanceof IContentAssistantExtension4 && fContentAssistant instanceof IContentAssistantExtension4)
376 fContentAssistantFacade= new ContentAssistantFacade(fContentAssistant);
377 fContentAssistantInstalled= true;
378 }
379
380 fQuickAssistAssistant= configuration.getQuickAssistAssistant(this);
381 if (fQuickAssistAssistant !is null) {
382 fQuickAssistAssistant.install(this);
383 fQuickAssistAssistantInstalled= true;
384 }
385
386 fContentFormatter= configuration.getContentFormatter(this);
387
388 fInformationPresenter= configuration.getInformationPresenter(this);
389 if (fInformationPresenter !is null)
390 fInformationPresenter.install(this);
391
392 setUndoManager(configuration.getUndoManager(this));
393
394 getTextWidget().setTabs(configuration.getTabWidth(this));
395
396 setAnnotationHover(configuration.getAnnotationHover(this));
397 setOverviewRulerAnnotationHover(configuration.getOverviewRulerAnnotationHover(this));
398
399 setHoverControlCreator(configuration.getInformationControlCreator(this));
400
401 setHyperlinkPresenter(configuration.getHyperlinkPresenter(this));
402 IHyperlinkDetector[] hyperlinkDetectors= configuration.getHyperlinkDetectors(this);
403 int eventStateMask= configuration.getHyperlinkStateMask(this);
404 setHyperlinkDetectors(hyperlinkDetectors, eventStateMask);
405
406 // install content type specific plug-ins
407 String[] types= configuration.getConfiguredContentTypes(this);
408 for (int i= 0; i < types.length; i++) {
409
410 String t= types[i];
411
412 setAutoEditStrategies(configuration.getAutoEditStrategies(this, t), t);
413 setTextDoubleClickStrategy(configuration.getDoubleClickStrategy(this, t), t);
414
415 int[] stateMasks= configuration.getConfiguredTextHoverStateMasks(this, t);
416 if (stateMasks !is null) {
417 for (int j= 0; j < stateMasks.length; j++) {
418 int stateMask= stateMasks[j];
419 setTextHover(configuration.getTextHover(this, t, stateMask), t, stateMask);
420 }
421 } else {
422 setTextHover(configuration.getTextHover(this, t), t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
423 }
424
425 String[] prefixes= configuration.getIndentPrefixes(this, t);
426 if (prefixes !is null && prefixes.length > 0)
427 setIndentPrefixes(prefixes, t);
428
429 prefixes= configuration.getDefaultPrefixes(this, t);
430 if (prefixes !is null && prefixes.length > 0)
431 setDefaultPrefixes(prefixes, t);
432 }
433
434 activatePlugins();
435 }
436
437 /**
438 * After this method has been executed the caller knows that any installed annotation hover has been installed.
439 */
440 protected void ensureAnnotationHoverManagerInstalled() {
441 if (fVerticalRuler !is null && (fAnnotationHover !is null || !isVerticalRulerOnlyShowingAnnotations()) && fVerticalRulerHoveringController is null && fHoverControlCreator !is null) {
442 fVerticalRulerHoveringController= new AnnotationBarHoverManager(fVerticalRuler, this, fAnnotationHover, fHoverControlCreator);
443 fVerticalRulerHoveringController.install(fVerticalRuler.getControl());
444 fVerticalRulerHoveringController.getInternalAccessor().setInformationControlReplacer(new StickyHoverManager(this));
445 }
446 }
447
448 /**
449 * After this method has been executed the caller knows that any installed overview hover has been installed.
450 */
451 protected void ensureOverviewHoverManagerInstalled() {
452 if (fOverviewRuler !is null && fOverviewRulerAnnotationHover !is null && fOverviewRulerHoveringController is null && fHoverControlCreator !is null) {
453 fOverviewRulerHoveringController= new OverviewRulerHoverManager(fOverviewRuler, this, fOverviewRulerAnnotationHover, fHoverControlCreator);
454 fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
455 fOverviewRulerHoveringController.getInternalAccessor().setInformationControlReplacer(new StickyHoverManager(this));
456 }
457 }
458
459 /*
460 * @see dwtx.jface.text.TextViewer#setHoverEnrichMode(dwtx.jface.text.ITextViewerExtension8.EnrichMode)
461 * @since 3.4
462 */
463 public void setHoverEnrichMode(EnrichMode mode) {
464 super.setHoverEnrichMode(mode);
465 if (fVerticalRulerHoveringController !is null)
466 fVerticalRulerHoveringController.getInternalAccessor().setHoverEnrichMode(mode);
467 if (fOverviewRulerHoveringController !is null)
468 fOverviewRulerHoveringController.getInternalAccessor().setHoverEnrichMode(mode);
469 }
470
471 /*
472 * @see TextViewer#activatePlugins()
473 */
474 public void activatePlugins() {
475 ensureAnnotationHoverManagerInstalled();
476 ensureOverviewHoverManagerInstalled();
477 super.activatePlugins();
478 }
479
480 /*
481 * @see ISourceViewer#setDocument(IDocument, IAnnotationModel)
482 */
483 public void setDocument(IDocument document) {
484 setDocument(document, null, -1, -1);
485 }
486
487 /*
488 * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
489 */
490 public void setDocument(IDocument document, int visibleRegionOffset, int visibleRegionLength) {
491 setDocument(document, null, visibleRegionOffset, visibleRegionLength);
492 }
493
494 /*
495 * @see ISourceViewer#setDocument(IDocument, IAnnotationModel)
496 */
497 public void setDocument(IDocument document, IAnnotationModel annotationModel) {
498 setDocument(document, annotationModel, -1, -1);
499 }
500
501 /**
502 * Creates the visual annotation model on top of the given annotation model.
503 *
504 * @param annotationModel the wrapped annotation model
505 * @return the visual annotation model on top of the given annotation model
506 * @since 3.0
507 */
508 protected IAnnotationModel createVisualAnnotationModel(IAnnotationModel annotationModel) {
509 IAnnotationModelExtension model= new AnnotationModel();
510 model.addAnnotationModel(MODEL_ANNOTATION_MODEL, annotationModel);
511 return (IAnnotationModel) model;
512 }
513
514 /**
515 * Disposes the visual annotation model.
516 *
517 * @since 3.1
518 */
519 protected void disposeVisualAnnotationModel() {
520 if (fVisualAnnotationModel !is null) {
521 if (getDocument() !is null)
522 fVisualAnnotationModel.disconnect(getDocument());
523
524 if ( fVisualAnnotationModel instanceof IAnnotationModelExtension)
525 ((IAnnotationModelExtension)fVisualAnnotationModel).removeAnnotationModel(MODEL_ANNOTATION_MODEL);
526
527 fVisualAnnotationModel= null;
528 }
529 }
530
531 /*
532 * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
533 */
534 public void setDocument(IDocument document, IAnnotationModel annotationModel, int modelRangeOffset, int modelRangeLength) {
535 disposeVisualAnnotationModel();
536
537 if (annotationModel !is null && document !is null) {
538 fVisualAnnotationModel= createVisualAnnotationModel(annotationModel);
539 fVisualAnnotationModel.connect(document);
540 }
541
542 if (modelRangeOffset is -1 && modelRangeLength is -1)
543 super.setDocument(document);
544 else
545 super.setDocument(document, modelRangeOffset, modelRangeLength);
546
547 if (fVerticalRuler !is null)
548 fVerticalRuler.setModel(fVisualAnnotationModel);
549
550 if (fOverviewRuler !is null)
551 fOverviewRuler.setModel(fVisualAnnotationModel);
552 }
553
554 /*
555 * @see ISourceViewer#getAnnotationModel()
556 */
557 public IAnnotationModel getAnnotationModel() {
558 if (fVisualAnnotationModel instanceof IAnnotationModelExtension) {
559 IAnnotationModelExtension extension= (IAnnotationModelExtension) fVisualAnnotationModel;
560 return extension.getAnnotationModel(MODEL_ANNOTATION_MODEL);
561 }
562 return null;
563 }
564
565 /*
566 * @see dwtx.jface.text.source.ISourceViewerExtension3#getQuickAssistAssistant()
567 * @since 3.2
568 */
569 public IQuickAssistAssistant getQuickAssistAssistant() {
570 return fQuickAssistAssistant;
571 }
572
573 /**
574 * {@inheritDoc}
575 *
576 * @since 3.4
577 */
578 public final ContentAssistantFacade getContentAssistantFacade() {
579 return fContentAssistantFacade;
580 }
581
582 /*
583 * @see dwtx.jface.text.source.ISourceViewerExtension3#getQuickAssistInvocationContext()
584 * @since 3.2
585 */
586 public IQuickAssistInvocationContext getQuickAssistInvocationContext() {
587 Point selection= getSelectedRange();
588 return new TextInvocationContext(this, selection.x, selection.x);
589 }
590
591 /*
592 * @see dwtx.jface.text.source.ISourceViewerExtension2#getVisualAnnotationModel()
593 * @since 3.0
594 */
595 public IAnnotationModel getVisualAnnotationModel() {
596 return fVisualAnnotationModel;
597 }
598
599 /*
600 * @see dwtx.jface.text.source.ISourceViewerExtension2#unconfigure()
601 * @since 3.0
602 */
603 public void unconfigure() {
604 clearRememberedSelection();
605
606 if (fPresentationReconciler !is null) {
607 fPresentationReconciler.uninstall();
608 fPresentationReconciler= null;
609 }
610
611 if (fReconciler !is null) {
612 fReconciler.uninstall();
613 fReconciler= null;
614 }
615
616 if (fContentAssistant !is null) {
617 fContentAssistant.uninstall();
618 fContentAssistantInstalled= false;
619 fContentAssistant= null;
620 if (fContentAssistantFacade !is null)
621 fContentAssistantFacade= null;
622 }
623
624 if (fQuickAssistAssistant !is null) {
625 fQuickAssistAssistant.uninstall();
626 fQuickAssistAssistantInstalled= false;
627 fQuickAssistAssistant= null;
628 }
629
630 fContentFormatter= null;
631
632 if (fInformationPresenter !is null) {
633 fInformationPresenter.uninstall();
634 fInformationPresenter= null;
635 }
636
637 fAutoIndentStrategies= null;
638 fDoubleClickStrategies= null;
639 fTextHovers= null;
640 fIndentChars= null;
641 fDefaultPrefixChars= null;
642
643 if (fVerticalRulerHoveringController !is null) {
644 fVerticalRulerHoveringController.dispose();
645 fVerticalRulerHoveringController= null;
646 }
647
648 if (fOverviewRulerHoveringController !is null) {
649 fOverviewRulerHoveringController.dispose();
650 fOverviewRulerHoveringController= null;
651 }
652
653 if (fUndoManager !is null) {
654 fUndoManager.disconnect();
655 fUndoManager= null;
656 }
657
658 setHyperlinkDetectors(null, DWT.NONE);
659 }
660
661 /*
662 * @see dwtx.jface.text.TextViewer#handleDispose()
663 */
664 protected void handleDispose() {
665 unconfigure();
666
667 disposeVisualAnnotationModel();
668
669 fVerticalRuler= null;
670
671 fOverviewRuler= null;
672
673 // http://dev.eclipse.org/bugs/show_bug.cgi?id=15300
674 fComposite= null;
675
676 super.handleDispose();
677 }
678
679 /*
680 * @see ITextOperationTarget#canDoOperation(int)
681 */
682 public bool canDoOperation(int operation) {
683
684 if (getTextWidget() is null || (!redraws() && operation !is FORMAT))
685 return false;
686
687 if (operation is CONTENTASSIST_PROPOSALS)
688 return fContentAssistant !is null && fContentAssistantInstalled && isEditable();
689
690 if (operation is CONTENTASSIST_CONTEXT_INFORMATION)
691 return fContentAssistant !is null && fContentAssistantInstalled && isEditable();
692
693 if (operation is QUICK_ASSIST)
694 return fQuickAssistAssistant !is null && fQuickAssistAssistantInstalled && isEditable();
695
696 if (operation is INFORMATION)
697 return fInformationPresenter !is null;
698
699 if (operation is FORMAT) {
700 return fContentFormatter !is null && isEditable();
701 }
702
703 return super.canDoOperation(operation);
704 }
705
706 /**
707 * Creates a new formatting context for a format operation.
708 * <p>
709 * After the use of the context, clients are required to call
710 * its <code>dispose</code> method.
711 *
712 * @return The new formatting context
713 * @since 3.0
714 */
715 protected IFormattingContext createFormattingContext() {
716 return new FormattingContext();
717 }
718
719 /**
720 * Remembers and returns the current selection. The saved selection can be restored
721 * by calling <code>restoreSelection()</code>.
722 *
723 * @return the current selection
724 * @see dwtx.jface.text.ITextViewer#getSelectedRange()
725 * @since 3.0
726 */
727 protected Point rememberSelection() {
728
729 final Point selection= getSelectedRange();
730 final IDocument document= getDocument();
731
732 if (fSelections.isEmpty()) {
733 fSelectionCategory= _SELECTION_POSITION_CATEGORY + hashCode();
734 fSelectionUpdater= new NonDeletingPositionUpdater(fSelectionCategory);
735 document.addPositionCategory(fSelectionCategory);
736 document.addPositionUpdater(fSelectionUpdater);
737 }
738
739 try {
740
741 final Position position= new Position(selection.x, selection.y);
742 document.addPosition(fSelectionCategory, position);
743 fSelections.push(position);
744
745 } catch (BadLocationException exception) {
746 // Should not happen
747 } catch (BadPositionCategoryException exception) {
748 // Should not happen
749 }
750
751 return selection;
752 }
753
754 /**
755 * Restores a previously saved selection in the document.
756 * <p>
757 * If no selection was previously saved, nothing happens.
758 *
759 * @since 3.0
760 */
761 protected void restoreSelection() {
762
763 if (!fSelections.isEmpty()) {
764
765 final IDocument document= getDocument();
766 final Position position= (Position) fSelections.pop();
767
768 try {
769 document.removePosition(fSelectionCategory, position);
770 Point currentSelection= getSelectedRange();
771 if (currentSelection is null || currentSelection.x !is position.getOffset() || currentSelection.y !is position.getLength())
772 setSelectedRange(position.getOffset(), position.getLength());
773
774 if (fSelections.isEmpty())
775 clearRememberedSelection();
776 } catch (BadPositionCategoryException exception) {
777 // Should not happen
778 }
779 }
780 }
781
782 protected void clearRememberedSelection() {
783 if (!fSelections.isEmpty())
784 fSelections.clear();
785
786 IDocument document= getDocument();
787 if (document !is null && fSelectionUpdater !is null) {
788 document.removePositionUpdater(fSelectionUpdater);
789 try {
790 document.removePositionCategory(fSelectionCategory);
791 } catch (BadPositionCategoryException e) {
792 // ignore
793 }
794 }
795 fSelectionUpdater= null;
796 fSelectionCategory= null;
797 }
798
799 /*
800 * @see ITextOperationTarget#doOperation(int)
801 */
802 public void doOperation(int operation) {
803
804 if (getTextWidget() is null || (!redraws() && operation !is FORMAT))
805 return;
806
807 switch (operation) {
808 case CONTENTASSIST_PROPOSALS:
809 fContentAssistant.showPossibleCompletions();
810 return;
811 case CONTENTASSIST_CONTEXT_INFORMATION:
812 fContentAssistant.showContextInformation();
813 return;
814 case QUICK_ASSIST:
815 // FIXME: must find a way to post to the status line
816 /* String msg= */ fQuickAssistAssistant.showPossibleQuickAssists();
817 // setStatusLineErrorMessage(msg);
818 return;
819 case INFORMATION:
820 fInformationPresenter.showInformation();
821 return;
822 case FORMAT:
823 {
824 final Point selection= rememberSelection();
825 final IRewriteTarget target= getRewriteTarget();
826 final IDocument document= getDocument();
827 IFormattingContext context= null;
828 DocumentRewriteSession rewriteSession= null;
829
830 if (document instanceof IDocumentExtension4) {
831 IDocumentExtension4 extension= (IDocumentExtension4) document;
832 DocumentRewriteSessionType type= selection.y is 0 || selection.y > 1000 ? DocumentRewriteSessionType.SEQUENTIAL : DocumentRewriteSessionType.UNRESTRICTED_SMALL;
833 rewriteSession= extension.startRewriteSession(type);
834 } else {
835 setRedraw(false);
836 target.beginCompoundChange();
837 }
838
839 try {
840
841 final String rememberedContents= document.get();
842
843 try {
844
845 if (fContentFormatter instanceof IContentFormatterExtension) {
846 final IContentFormatterExtension extension= (IContentFormatterExtension) fContentFormatter;
847 context= createFormattingContext();
848 if (selection.y is 0) {
849 context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.TRUE);
850 } else {
851 context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.FALSE);
852 context.setProperty(FormattingContextProperties.CONTEXT_REGION, new Region(selection.x, selection.y));
853 }
854 extension.format(document, context);
855 } else {
856 IRegion r;
857 if (selection.y is 0) {
858 IRegion coverage= getModelCoverage();
859 r= coverage is null ? new Region(0, 0) : coverage;
860 } else {
861 r= new Region(selection.x, selection.y);
862 }
863 fContentFormatter.format(document, r);
864 }
865
866 updateSlaveDocuments(document);
867
868 } catch (RuntimeException x) {
869 // fire wall for https://bugs.eclipse.org/bugs/show_bug.cgi?id=47472
870 // if something went wrong we undo the changes we just did
871 // TODO to be removed after 3.0 M8
872 document.set(rememberedContents);
873 throw x;
874 }
875
876 } finally {
877
878 if (document instanceof IDocumentExtension4) {
879 IDocumentExtension4 extension= (IDocumentExtension4) document;
880 extension.stopRewriteSession(rewriteSession);
881 } else {
882 target.endCompoundChange();
883 setRedraw(true);
884 }
885
886 restoreSelection();
887 if (context !is null)
888 context.dispose();
889 }
890 return;
891 }
892 default:
893 super.doOperation(operation);
894 }
895 }
896
897 /**
898 * Updates all slave documents of the given document. This default implementation calls <code>updateSlaveDocument</code>
899 * for their current visible range. Subclasses may reimplement.
900 *
901 * @param masterDocument the master document
902 * @since 3.0
903 */
904 protected void updateSlaveDocuments(IDocument masterDocument) {
905 ISlaveDocumentManager manager= getSlaveDocumentManager();
906 if (manager instanceof ISlaveDocumentManagerExtension) {
907 ISlaveDocumentManagerExtension extension= (ISlaveDocumentManagerExtension) manager;
908 IDocument[] slaves= extension.getSlaveDocuments(masterDocument);
909 if (slaves !is null) {
910 for (int i= 0; i < slaves.length; i++) {
911 if (slaves[i] instanceof ChildDocument) {
912 ChildDocument child= (ChildDocument) slaves[i];
913 Position p= child.getParentDocumentRange();
914 try {
915
916 if (!updateSlaveDocument(child, p.getOffset(), p.getLength()))
917 child.repairLineInformation();
918
919 } catch (BadLocationException e) {
920 // ignore
921 }
922 }
923 }
924 }
925 }
926 }
927
928 /*
929 * @see ITextOperationTargetExtension#enableOperation(int, bool)
930 * @since 2.0
931 */
932 public void enableOperation(int operation, bool enable) {
933
934 switch (operation) {
935 case CONTENTASSIST_PROPOSALS:
936 case CONTENTASSIST_CONTEXT_INFORMATION: {
937
938 if (fContentAssistant is null)
939 return;
940
941 if (enable) {
942 if (!fContentAssistantInstalled) {
943 fContentAssistant.install(this);
944 fContentAssistantInstalled= true;
945 }
946 } else if (fContentAssistantInstalled) {
947 fContentAssistant.uninstall();
948 fContentAssistantInstalled= false;
949 }
950 break;
951 }
952 case QUICK_ASSIST: {
953
954 if (fQuickAssistAssistant is null)
955 return;
956
957 if (enable) {
958 if (!fQuickAssistAssistantInstalled) {
959 fQuickAssistAssistant.install(this);
960 fQuickAssistAssistantInstalled= true;
961 }
962 } else if (fContentAssistantInstalled) {
963 fQuickAssistAssistant.uninstall();
964 fContentAssistantInstalled= false;
965 }
966 }
967 }
968 }
969
970 /*
971 * @see ISourceViewer#setRangeIndicator(Annotation)
972 */
973 public void setRangeIndicator(Annotation rangeIndicator) {
974 fRangeIndicator= rangeIndicator;
975 }
976
977 /*
978 * @see ISourceViewer#setRangeIndication(int, int, bool)
979 */
980 public void setRangeIndication(int start, int length, bool moveCursor) {
981
982 if (moveCursor) {
983 setSelectedRange(start, 0);
984 revealRange(start, length);
985 }
986
987 if (fRangeIndicator !is null && fVisualAnnotationModel instanceof IAnnotationModelExtension) {
988 IAnnotationModelExtension extension= (IAnnotationModelExtension) fVisualAnnotationModel;
989 extension.modifyAnnotationPosition(fRangeIndicator, new Position(start, length));
990 }
991 }
992
993 /*
994 * @see ISourceViewer#getRangeIndication()
995 */
996 public IRegion getRangeIndication() {
997 if (fRangeIndicator !is null && fVisualAnnotationModel !is null) {
998 Position position= fVisualAnnotationModel.getPosition(fRangeIndicator);
999 if (position !is null)
1000 return new Region(position.getOffset(), position.getLength());
1001 }
1002
1003 return null;
1004 }
1005
1006 /*
1007 * @see ISourceViewer#removeRangeIndication()
1008 */
1009 public void removeRangeIndication() {
1010 if (fRangeIndicator !is null && fVisualAnnotationModel !is null)
1011 fVisualAnnotationModel.removeAnnotation(fRangeIndicator);
1012 }
1013
1014 /*
1015 * @see ISourceViewer#showAnnotations(bool)
1016 */
1017 public void showAnnotations(bool show) {
1018 bool old= fIsVerticalRulerVisible;
1019
1020 fIsVerticalRulerVisible= (fVerticalRuler !is null && (show || !isVerticalRulerOnlyShowingAnnotations()));
1021 if (old !is fIsVerticalRulerVisible && fComposite !is null && !fComposite.isDisposed())
1022 fComposite.layout();
1023
1024 if (fIsVerticalRulerVisible && show)
1025 ensureAnnotationHoverManagerInstalled();
1026 else if (fVerticalRulerHoveringController !is null) {
1027 fVerticalRulerHoveringController.dispose();
1028 fVerticalRulerHoveringController= null;
1029 }
1030 }
1031
1032 /**
1033 * Tells whether the vertical ruler only acts as annotation ruler.
1034 *
1035 * @return <code>true</code> if the vertical ruler only show annotations
1036 * @since 3.3
1037 */
1038 private bool isVerticalRulerOnlyShowingAnnotations() {
1039 if (fVerticalRuler instanceof VerticalRuler)
1040 return true;
1041
1042 if (fVerticalRuler instanceof CompositeRuler) {
1043 Iterator iter= ((CompositeRuler)fVerticalRuler).getDecoratorIterator();
1044 return iter.hasNext() && iter.next() instanceof AnnotationRulerColumn && !iter.hasNext();
1045 }
1046 return false;
1047 }
1048
1049 /**
1050 * Returns the vertical ruler of this viewer.
1051 *
1052 * @return the vertical ruler of this viewer
1053 * @since 3.0
1054 */
1055 protected final IVerticalRuler getVerticalRuler() {
1056 return fVerticalRuler;
1057 }
1058
1059 /*
1060 * @see dwtx.jface.text.source.ISourceViewerExtension#showAnnotationsOverview(bool)
1061 * @since 2.1
1062 */
1063 public void showAnnotationsOverview(bool show) {
1064 bool old= fIsOverviewRulerVisible;
1065 fIsOverviewRulerVisible= (show && fOverviewRuler !is null);
1066 if (old !is fIsOverviewRulerVisible) {
1067 if (fComposite !is null && !fComposite.isDisposed())
1068 fComposite.layout();
1069 if (fIsOverviewRulerVisible) {
1070 ensureOverviewHoverManagerInstalled();
1071 } else if (fOverviewRulerHoveringController !is null) {
1072 fOverviewRulerHoveringController.dispose();
1073 fOverviewRulerHoveringController= null;
1074 }
1075 }
1076 }
1077
1078 /*
1079 * @see dwtx.jface.text.source.ISourceViewer#getCurrentAnnotationHover()
1080 * @since 3.2
1081 */
1082 public IAnnotationHover getCurrentAnnotationHover() {
1083 if (fVerticalRulerHoveringController is null)
1084 return null;
1085 return fVerticalRulerHoveringController.getCurrentAnnotationHover();
1086 }
1087 }