Mercurial > projects > dwt-addons
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 } |