KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > source > SourceViewer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  *******************************************************************************/

11 package org.eclipse.jface.text.source;
12
13 import java.util.Iterator JavaDoc;
14 import java.util.Stack JavaDoc;
15
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.graphics.Point;
18 import org.eclipse.swt.graphics.Rectangle;
19 import org.eclipse.swt.widgets.Canvas;
20 import org.eclipse.swt.widgets.Composite;
21 import org.eclipse.swt.widgets.Control;
22 import org.eclipse.swt.widgets.Layout;
23
24 import org.eclipse.jface.internal.text.NonDeletingPositionUpdater;
25
26 import org.eclipse.jface.text.AbstractHoverInformationControlManager;
27 import org.eclipse.jface.text.BadLocationException;
28 import org.eclipse.jface.text.BadPositionCategoryException;
29 import org.eclipse.jface.text.DocumentRewriteSession;
30 import org.eclipse.jface.text.DocumentRewriteSessionType;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IDocumentExtension4;
33 import org.eclipse.jface.text.IPositionUpdater;
34 import org.eclipse.jface.text.IRegion;
35 import org.eclipse.jface.text.IRewriteTarget;
36 import org.eclipse.jface.text.ISlaveDocumentManager;
37 import org.eclipse.jface.text.ISlaveDocumentManagerExtension;
38 import org.eclipse.jface.text.ITextViewerExtension2;
39 import org.eclipse.jface.text.Position;
40 import org.eclipse.jface.text.Region;
41 import org.eclipse.jface.text.TextViewer;
42 import org.eclipse.jface.text.contentassist.IContentAssistant;
43 import org.eclipse.jface.text.formatter.FormattingContext;
44 import org.eclipse.jface.text.formatter.FormattingContextProperties;
45 import org.eclipse.jface.text.formatter.IContentFormatter;
46 import org.eclipse.jface.text.formatter.IContentFormatterExtension;
47 import org.eclipse.jface.text.formatter.IFormattingContext;
48 import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
49 import org.eclipse.jface.text.information.IInformationPresenter;
50 import org.eclipse.jface.text.presentation.IPresentationReconciler;
51 import org.eclipse.jface.text.projection.ChildDocument;
52 import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
53 import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext;
54 import org.eclipse.jface.text.reconciler.IReconciler;
55
56 /**
57  * SWT based implementation of
58  * {@link org.eclipse.jface.text.source.ISourceViewer} and its extension
59  * interfaces. The same rules apply as for
60  * {@link org.eclipse.jface.text.TextViewer}. A source viewer uses an
61  * <code>IVerticalRuler</code> as its annotation presentation area. The
62  * vertical ruler is a small strip shown left of the viewer's text widget. A
63  * source viewer uses an <code>IOverviewRuler</code> as its presentation area
64  * for the annotation overview. The overview ruler is a small strip shown right
65  * of the viewer's text widget.
66  * <p>
67  * Clients are supposed to instantiate a source viewer and subsequently to
68  * communicate with it exclusively using the <code>ISourceViewer</code> and
69  * its extension interfaces.</p>
70  * <p>
71  * Clients may subclass this class but should expect some breakage by future releases.</p>
72  */

73 public class SourceViewer extends TextViewer implements ISourceViewer, ISourceViewerExtension, ISourceViewerExtension2, ISourceViewerExtension3 {
74
75
76     /**
77      * Layout of a source viewer. Vertical ruler, text widget, and overview ruler are shown side by side.
78      */

79     protected class RulerLayout extends Layout {
80
81         /** The gap between the text viewer and the vertical ruler. */
82         protected int fGap;
83
84         /**
85          * Creates a new ruler layout with the given gap between text viewer and vertical ruler.
86          *
87          * @param gap the gap between text viewer and vertical ruler
88          */

89         public RulerLayout(int gap) {
90             fGap= gap;
91         }
92
93         /*
94          * @see Layout#computeSize(Composite, int, int, boolean)
95          */

96         protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
97             Control[] children= composite.getChildren();
98             Point s= children[children.length - 1].computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
99             if (fVerticalRuler != null && fIsVerticalRulerVisible)
100                 s.x += fVerticalRuler.getWidth() + fGap;
101             return s;
102         }
103
104         /*
105          * @see Layout#layout(Composite, boolean)
106          */

107         protected void layout(Composite composite, boolean flushCache) {
108             Rectangle clArea= composite.getClientArea();
109             Rectangle trim= getTextWidget().computeTrim(0, 0, 0, 0);
110             int topTrim= - trim.y;
111             int scrollbarHeight= trim.height - topTrim; // scrollbar is only under the client area
112

113             int x= clArea.x;
114             int width= clArea.width;
115
116             if (fOverviewRuler != null && fIsOverviewRulerVisible) {
117                 int overviewRulerWidth= fOverviewRuler.getWidth();
118                 fOverviewRuler.getControl().setBounds(clArea.x + clArea.width - overviewRulerWidth - 1, clArea.y + scrollbarHeight, overviewRulerWidth, clArea.height - 3*scrollbarHeight);
119                 fOverviewRuler.getHeaderControl().setBounds(clArea.x + clArea.width - overviewRulerWidth - 1, clArea.y, overviewRulerWidth, scrollbarHeight);
120
121                 width -= overviewRulerWidth + fGap;
122             }
123
124             if (fVerticalRuler != null && fIsVerticalRulerVisible) {
125                 int verticalRulerWidth= fVerticalRuler.getWidth();
126                 final Control verticalRulerControl= fVerticalRuler.getControl();
127                 int oldWidth= verticalRulerControl.getBounds().width;
128                 verticalRulerControl.setBounds(clArea.x, clArea.y + topTrim, verticalRulerWidth, clArea.height - scrollbarHeight - topTrim);
129                 if (flushCache && getVisualAnnotationModel() != null && oldWidth == verticalRulerWidth)
130                     verticalRulerControl.redraw();
131
132                 x += verticalRulerWidth + fGap;
133                 width -= verticalRulerWidth + fGap;
134             }
135
136             getTextWidget().setBounds(x, clArea.y, width, clArea.height);
137         }
138     }
139
140     /**
141      * The size of the gap between the vertical ruler and the text widget
142      * (value <code>2</code>).
143      * <p>
144      * Note: As of 3.2, the text editor framework is no longer using 2 as
145      * gap but 1, see {{@link #GAP_SIZE_1 }.
146      * </p>
147      */

148     protected final static int GAP_SIZE= 2;
149     /**
150      * The size of the gap between the vertical ruler and the text widget
151      * (value <code>1</code>).
152      * @since 3.2
153      */

154     protected final static int GAP_SIZE_1= 1;
155     /**
156      * Partial name of the position category to manage remembered selections.
157      * @since 3.0
158      */

159     protected final static String JavaDoc _SELECTION_POSITION_CATEGORY= "__selection_category"; //$NON-NLS-1$
160
/**
161      * Key of the model annotation model inside the visual annotation model.
162      * @since 3.0
163      */

164     protected final static Object JavaDoc MODEL_ANNOTATION_MODEL= new Object JavaDoc();
165
166     /** The viewer's content assistant */
167     protected IContentAssistant fContentAssistant;
168     /**
169      * Flag indicating whether the viewer's content assistant is installed.
170      * @since 2.0
171      */

172     protected boolean fContentAssistantInstalled;
173     /**
174      * This viewer's quick assist assistant.
175      * @since 3.2
176      */

177     protected IQuickAssistAssistant fQuickAssistAssistant;
178     /**
179      * Flag indicating whether this viewer's quick assist assistant is installed.
180      * @since 3.2
181      */

182     protected boolean fQuickAssistAssistantInstalled;
183     /** The viewer's content formatter */
184     protected IContentFormatter fContentFormatter;
185     /** The viewer's model reconciler */
186     protected IReconciler fReconciler;
187     /** The viewer's presentation reconciler */
188     protected IPresentationReconciler fPresentationReconciler;
189     /** The viewer's annotation hover */
190     protected IAnnotationHover fAnnotationHover;
191     /**
192      * Stack of saved selections in the underlying document
193      * @since 3.0
194      */

195     protected final Stack JavaDoc fSelections= new Stack JavaDoc();
196     /**
197      * Position updater for saved selections
198      * @since 3.0
199      */

200     protected IPositionUpdater fSelectionUpdater= null;
201     /**
202      * Position category used by the selection updater
203      * @since 3.0
204      */

205     protected String JavaDoc fSelectionCategory;
206     /**
207      * The viewer's overview ruler annotation hover
208      * @since 3.0
209      */

210     protected IAnnotationHover fOverviewRulerAnnotationHover;
211     /**
212      * The viewer's information presenter
213      * @since 2.0
214      */

215     protected IInformationPresenter fInformationPresenter;
216
217     /** Visual vertical ruler */
218     private IVerticalRuler fVerticalRuler;
219     /** Visibility of vertical ruler */
220     private boolean fIsVerticalRulerVisible;
221     /** The SWT widget used when supporting a vertical ruler */
222     private Composite fComposite;
223     /** The vertical ruler's annotation model */
224     private IAnnotationModel fVisualAnnotationModel;
225     /** The viewer's range indicator to be shown in the vertical ruler */
226     private Annotation fRangeIndicator;
227     /** The viewer's vertical ruler hovering controller */
228     private AnnotationBarHoverManager fVerticalRulerHoveringController;
229     /**
230      * The viewer's overview ruler hovering controller
231      * @since 2.1
232      */

233     private AbstractHoverInformationControlManager fOverviewRulerHoveringController;
234
235     /**
236      * The overview ruler.
237      * @since 2.1
238      */

239     private IOverviewRuler fOverviewRuler;
240     /**
241      * The visibility of the overview ruler
242      * @since 2.1
243      */

244     private boolean fIsOverviewRulerVisible;
245
246
247     /**
248      * Constructs a new source viewer. The vertical ruler is initially visible.
249      * The viewer has not yet been initialized with a source viewer configuration.
250      *
251      * @param parent the parent of the viewer's control
252      * @param ruler the vertical ruler used by this source viewer
253      * @param styles the SWT style bits for the viewer's control,
254      * <em>if <code>SWT.WRAP</code> is set then a custom document adapter needs to be provided, see {@link #createDocumentAdapter()}
255      */

256     public SourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
257         this(parent, ruler, null, false, styles);
258     }
259
260     /**
261      * Constructs a new source viewer. The vertical ruler is initially visible.
262      * The overview ruler visibility is controlled by the value of <code>showAnnotationsOverview</code>.
263      * The viewer has not yet been initialized with a source viewer configuration.
264      *
265      * @param parent the parent of the viewer's control
266      * @param verticalRuler the vertical ruler used by this source viewer
267      * @param overviewRuler the overview ruler
268      * @param showAnnotationsOverview <code>true</code> if the overview ruler should be visible, <code>false</code> otherwise
269      * @param styles the SWT style bits for the viewer's control,
270      * <em>if <code>SWT.WRAP</code> is set then a custom document adapter needs to be provided, see {@link #createDocumentAdapter()}
271      * @since 2.1
272      */

273     public SourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean showAnnotationsOverview, int styles) {
274         super();
275
276         fVerticalRuler= verticalRuler;
277         fIsVerticalRulerVisible= (verticalRuler != null);
278         fOverviewRuler= overviewRuler;
279         fIsOverviewRulerVisible= (showAnnotationsOverview && overviewRuler != null);
280
281         createControl(parent, styles);
282     }
283
284     /*
285      * @see TextViewer#createControl(Composite, int)
286      */

287     protected void createControl(Composite parent, int styles) {
288
289         if (fVerticalRuler != null || fOverviewRuler != null) {
290             styles= (styles & ~SWT.BORDER);
291             fComposite= new Canvas(parent, SWT.NONE);
292             fComposite.setLayout(createLayout());
293             parent= fComposite;
294         }
295
296         super.createControl(parent, styles);
297
298         if (fVerticalRuler != null)
299             fVerticalRuler.createControl(fComposite, this);
300         if (fOverviewRuler != null)
301             fOverviewRuler.createControl(fComposite, this);
302     }
303
304     /**
305      * Creates the layout used for this viewer.
306      * Subclasses may override this method.
307      *
308      * @return the layout used for this viewer
309      * @since 3.0
310      */

311     protected Layout createLayout() {
312         return new RulerLayout(GAP_SIZE_1);
313     }
314
315     /*
316      * @see TextViewer#getControl()
317      */

318     public Control getControl() {
319         if (fComposite != null)
320             return fComposite;
321         return super.getControl();
322     }
323
324     /*
325      * @see ISourceViewer#setAnnotationHover(IAnnotationHover)
326      */

327     public void setAnnotationHover(IAnnotationHover annotationHover) {
328         fAnnotationHover= annotationHover;
329     }
330
331     /**
332      * Sets the overview ruler's annotation hover of this source viewer.
333      * The annotation hover provides the information to be displayed in a hover
334      * popup window if requested over the overview rulers area. The annotation
335      * hover is assumed to be line oriented.
336      *
337      * @param annotationHover the hover to be used, <code>null</code> is a valid argument
338      * @since 3.0
339      */

340     public void setOverviewRulerAnnotationHover(IAnnotationHover annotationHover) {
341         fOverviewRulerAnnotationHover= annotationHover;
342     }
343
344     /*
345      * @see ISourceViewer#configure(SourceViewerConfiguration)
346      */

347     public void configure(SourceViewerConfiguration configuration) {
348
349         if (getTextWidget() == null)
350             return;
351
352         setDocumentPartitioning(configuration.getConfiguredDocumentPartitioning(this));
353
354         // install content type independent plug-ins
355
fPresentationReconciler= configuration.getPresentationReconciler(this);
356         if (fPresentationReconciler != null)
357             fPresentationReconciler.install(this);
358
359         fReconciler= configuration.getReconciler(this);
360         if (fReconciler != null)
361             fReconciler.install(this);
362
363         fContentAssistant= configuration.getContentAssistant(this);
364         if (fContentAssistant != null) {
365             fContentAssistant.install(this);
366             fContentAssistantInstalled= true;
367         }
368         
369         fQuickAssistAssistant= configuration.getQuickAssistAssistant(this);
370         if (fQuickAssistAssistant != null) {
371             fQuickAssistAssistant.install(this);
372             fQuickAssistAssistantInstalled= true;
373         }
374
375         fContentFormatter= configuration.getContentFormatter(this);
376
377         fInformationPresenter= configuration.getInformationPresenter(this);
378         if (fInformationPresenter != null)
379             fInformationPresenter.install(this);
380
381         setUndoManager(configuration.getUndoManager(this));
382
383         getTextWidget().setTabs(configuration.getTabWidth(this));
384
385         setAnnotationHover(configuration.getAnnotationHover(this));
386         setOverviewRulerAnnotationHover(configuration.getOverviewRulerAnnotationHover(this));
387
388         setHoverControlCreator(configuration.getInformationControlCreator(this));
389
390         setHyperlinkPresenter(configuration.getHyperlinkPresenter(this));
391         IHyperlinkDetector[] hyperlinkDetectors= configuration.getHyperlinkDetectors(this);
392         int eventStateMask= configuration.getHyperlinkStateMask(this);
393         setHyperlinkDetectors(hyperlinkDetectors, eventStateMask);
394
395         // install content type specific plug-ins
396
String JavaDoc[] types= configuration.getConfiguredContentTypes(this);
397         for (int i= 0; i < types.length; i++) {
398
399             String JavaDoc t= types[i];
400
401             setAutoEditStrategies(configuration.getAutoEditStrategies(this, t), t);
402             setTextDoubleClickStrategy(configuration.getDoubleClickStrategy(this, t), t);
403
404             int[] stateMasks= configuration.getConfiguredTextHoverStateMasks(this, t);
405             if (stateMasks != null) {
406                 for (int j= 0; j < stateMasks.length; j++) {
407                     int stateMask= stateMasks[j];
408                     setTextHover(configuration.getTextHover(this, t, stateMask), t, stateMask);
409                 }
410             } else {
411                 setTextHover(configuration.getTextHover(this, t), t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
412             }
413
414             String JavaDoc[] prefixes= configuration.getIndentPrefixes(this, t);
415             if (prefixes != null && prefixes.length > 0)
416                 setIndentPrefixes(prefixes, t);
417
418             prefixes= configuration.getDefaultPrefixes(this, t);
419             if (prefixes != null && prefixes.length > 0)
420                 setDefaultPrefixes(prefixes, t);
421         }
422
423         activatePlugins();
424     }
425
426     /**
427      * After this method has been executed the caller knows that any installed annotation hover has been installed.
428      */

429     protected void ensureAnnotationHoverManagerInstalled() {
430         if (fVerticalRuler != null && (fAnnotationHover != null || !isVerticalRulerOnlyShowingAnnotations()) && fVerticalRulerHoveringController == null && fHoverControlCreator != null) {
431             fVerticalRulerHoveringController= new AnnotationBarHoverManager(fVerticalRuler, this, fAnnotationHover, fHoverControlCreator);
432             fVerticalRulerHoveringController.install(fVerticalRuler.getControl());
433         }
434     }
435
436     /**
437      * After this method has been executed the caller knows that any installed overview hover has been installed.
438      */

439     protected void ensureOverviewHoverManagerInstalled() {
440         if (fOverviewRuler != null && fOverviewRulerAnnotationHover != null && fOverviewRulerHoveringController == null && fHoverControlCreator != null) {
441             fOverviewRulerHoveringController= new OverviewRulerHoverManager(fOverviewRuler, this, fOverviewRulerAnnotationHover, fHoverControlCreator);
442             fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
443         }
444     }
445
446     /*
447      * @see TextViewer#activatePlugins()
448      */

449     public void activatePlugins() {
450         ensureAnnotationHoverManagerInstalled();
451         ensureOverviewHoverManagerInstalled();
452         super.activatePlugins();
453     }
454
455     /*
456      * @see ISourceViewer#setDocument(IDocument, IAnnotationModel)
457      */

458     public void setDocument(IDocument document) {
459         setDocument(document, null, -1, -1);
460     }
461
462     /*
463      * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
464      */

465     public void setDocument(IDocument document, int visibleRegionOffset, int visibleRegionLength) {
466         setDocument(document, null, visibleRegionOffset, visibleRegionLength);
467     }
468
469     /*
470      * @see ISourceViewer#setDocument(IDocument, IAnnotationModel)
471      */

472     public void setDocument(IDocument document, IAnnotationModel annotationModel) {
473         setDocument(document, annotationModel, -1, -1);
474     }
475
476     /**
477      * Creates the visual annotation model on top of the given annotation model.
478      *
479      * @param annotationModel the wrapped annotation model
480      * @return the visual annotation model on top of the given annotation model
481      * @since 3.0
482      */

483     protected IAnnotationModel createVisualAnnotationModel(IAnnotationModel annotationModel) {
484         IAnnotationModelExtension model= new AnnotationModel();
485         model.addAnnotationModel(MODEL_ANNOTATION_MODEL, annotationModel);
486         return (IAnnotationModel) model;
487     }
488
489     /**
490      * Disposes the visual annotation model.
491      *
492      * @since 3.1
493      */

494     protected void disposeVisualAnnotationModel() {
495         if (fVisualAnnotationModel != null) {
496             if (getDocument() != null)
497                 fVisualAnnotationModel.disconnect(getDocument());
498         
499             if ( fVisualAnnotationModel instanceof IAnnotationModelExtension)
500                 ((IAnnotationModelExtension)fVisualAnnotationModel).removeAnnotationModel(MODEL_ANNOTATION_MODEL);
501             
502             fVisualAnnotationModel= null;
503         }
504     }
505
506     /*
507      * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
508      */

509     public void setDocument(IDocument document, IAnnotationModel annotationModel, int modelRangeOffset, int modelRangeLength) {
510         disposeVisualAnnotationModel();
511
512         if (annotationModel != null && document != null) {
513             fVisualAnnotationModel= createVisualAnnotationModel(annotationModel);
514             fVisualAnnotationModel.connect(document);
515         }
516
517         if (modelRangeOffset == -1 && modelRangeLength == -1)
518             super.setDocument(document);
519         else
520             super.setDocument(document, modelRangeOffset, modelRangeLength);
521
522         if (fVerticalRuler != null)
523             fVerticalRuler.setModel(fVisualAnnotationModel);
524
525         if (fOverviewRuler != null)
526             fOverviewRuler.setModel(fVisualAnnotationModel);
527     }
528
529     /*
530      * @see ISourceViewer#getAnnotationModel()
531      */

532     public IAnnotationModel getAnnotationModel() {
533         if (fVisualAnnotationModel instanceof IAnnotationModelExtension) {
534             IAnnotationModelExtension extension= (IAnnotationModelExtension) fVisualAnnotationModel;
535             return extension.getAnnotationModel(MODEL_ANNOTATION_MODEL);
536         }
537         return null;
538     }
539
540     /*
541      * @see org.eclipse.jface.text.source.ISourceViewerExtension3#getQuickAssistAssistant()
542      * @since 3.2
543      */

544     public IQuickAssistAssistant getQuickAssistAssistant() {
545         return fQuickAssistAssistant;
546     }
547
548     /*
549      * @see org.eclipse.jface.text.source.ISourceViewerExtension3#getQuickAssistInvocationContext()
550      * @since 3.2
551      */

552     public IQuickAssistInvocationContext getQuickAssistInvocationContext() {
553         Point selection= getSelectedRange();
554         return new TextInvocationContext(this, selection.x, selection.x);
555     }
556
557     /*
558      * @see org.eclipse.jface.text.source.ISourceViewerExtension2#getVisualAnnotationModel()
559      * @since 3.0
560      */

561     public IAnnotationModel getVisualAnnotationModel() {
562         return fVisualAnnotationModel;
563     }
564
565     /*
566      * @see org.eclipse.jface.text.source.ISourceViewerExtension2#unconfigure()
567      * @since 3.0
568      */

569     public void unconfigure() {
570         clearRememberedSelection();
571
572         if (fPresentationReconciler != null) {
573             fPresentationReconciler.uninstall();
574             fPresentationReconciler= null;
575         }
576
577         if (fReconciler != null) {
578             fReconciler.uninstall();
579             fReconciler= null;
580         }
581
582         if (fContentAssistant != null) {
583             fContentAssistant.uninstall();
584             fContentAssistantInstalled= false;
585             fContentAssistant= null;
586         }
587         
588         if (fQuickAssistAssistant != null) {
589             fQuickAssistAssistant.uninstall();
590             fQuickAssistAssistantInstalled= false;
591             fQuickAssistAssistant= null;
592         }
593
594         fContentFormatter= null;
595
596         if (fInformationPresenter != null) {
597             fInformationPresenter.uninstall();
598             fInformationPresenter= null;
599         }
600
601         fAutoIndentStrategies= null;
602         fDoubleClickStrategies= null;
603         fTextHovers= null;
604         fIndentChars= null;
605         fDefaultPrefixChars= null;
606
607         if (fVerticalRulerHoveringController != null) {
608             fVerticalRulerHoveringController.dispose();
609             fVerticalRulerHoveringController= null;
610         }
611
612         if (fOverviewRulerHoveringController != null) {
613             fOverviewRulerHoveringController.dispose();
614             fOverviewRulerHoveringController= null;
615         }
616
617         if (fUndoManager != null) {
618             fUndoManager.disconnect();
619             fUndoManager= null;
620         }
621
622         setHyperlinkDetectors(null, SWT.NONE);
623     }
624
625     /*
626      * @see org.eclipse.jface.text.TextViewer#handleDispose()
627      */

628     protected void handleDispose() {
629         unconfigure();
630
631         disposeVisualAnnotationModel();
632
633         fVerticalRuler= null;
634
635         fOverviewRuler= null;
636
637         // http://dev.eclipse.org/bugs/show_bug.cgi?id=15300
638
fComposite= null;
639
640         super.handleDispose();
641     }
642
643     /*
644      * @see ITextOperationTarget#canDoOperation(int)
645      */

646     public boolean canDoOperation(int operation) {
647
648         if (getTextWidget() == null || (!redraws() && operation != FORMAT))
649             return false;
650
651         if (operation == CONTENTASSIST_PROPOSALS)
652             return fContentAssistant != null && fContentAssistantInstalled && isEditable();
653
654         if (operation == CONTENTASSIST_CONTEXT_INFORMATION)
655             return fContentAssistant != null && fContentAssistantInstalled && isEditable();
656         
657         if (operation == QUICK_ASSIST)
658             return fQuickAssistAssistant != null && fQuickAssistAssistantInstalled && isEditable();
659
660         if (operation == INFORMATION)
661             return fInformationPresenter != null;
662
663         if (operation == FORMAT) {
664             return fContentFormatter != null && isEditable();
665         }
666
667         return super.canDoOperation(operation);
668     }
669
670     /**
671      * Creates a new formatting context for a format operation.
672      * <p>
673      * After the use of the context, clients are required to call
674      * its <code>dispose</code> method.
675      *
676      * @return The new formatting context
677      * @since 3.0
678      */

679     protected IFormattingContext createFormattingContext() {
680         return new FormattingContext();
681     }
682
683     /**
684      * Remembers and returns the current selection. The saved selection can be restored
685      * by calling <code>restoreSelection()</code>.
686      *
687      * @return the current selection
688      * @see org.eclipse.jface.text.ITextViewer#getSelectedRange()
689      * @since 3.0
690      */

691     protected Point rememberSelection() {
692
693         final Point selection= getSelectedRange();
694         final IDocument document= getDocument();
695
696         if (fSelections.isEmpty()) {
697             fSelectionCategory= _SELECTION_POSITION_CATEGORY + hashCode();
698             fSelectionUpdater= new NonDeletingPositionUpdater(fSelectionCategory);
699             document.addPositionCategory(fSelectionCategory);
700             document.addPositionUpdater(fSelectionUpdater);
701         }
702
703         try {
704
705             final Position position= new Position(selection.x, selection.y);
706             document.addPosition(fSelectionCategory, position);
707             fSelections.push(position);
708
709         } catch (BadLocationException exception) {
710             // Should not happen
711
} catch (BadPositionCategoryException exception) {
712             // Should not happen
713
}
714
715         return selection;
716     }
717
718     /**
719      * Restores a previously saved selection in the document.
720      * <p>
721      * If no selection was previously saved, nothing happens.
722      *
723      * @since 3.0
724      */

725     protected void restoreSelection() {
726
727         if (!fSelections.isEmpty()) {
728
729             final IDocument document= getDocument();
730             final Position position= (Position) fSelections.pop();
731
732             try {
733                 document.removePosition(fSelectionCategory, position);
734                 Point currentSelection= getSelectedRange();
735                 if (currentSelection == null || currentSelection.x != position.getOffset() || currentSelection.y != position.getLength())
736                     setSelectedRange(position.getOffset(), position.getLength());
737
738                 if (fSelections.isEmpty())
739                     clearRememberedSelection();
740             } catch (BadPositionCategoryException exception) {
741                 // Should not happen
742
}
743         }
744     }
745
746     protected void clearRememberedSelection() {
747         if (!fSelections.isEmpty())
748             fSelections.clear();
749
750         IDocument document= getDocument();
751         if (document != null && fSelectionUpdater != null) {
752             document.removePositionUpdater(fSelectionUpdater);
753             try {
754                 document.removePositionCategory(fSelectionCategory);
755             } catch (BadPositionCategoryException e) {
756                 // ignore
757
}
758         }
759         fSelectionUpdater= null;
760         fSelectionCategory= null;
761     }
762
763     /*
764      * @see ITextOperationTarget#doOperation(int)
765      */

766     public void doOperation(int operation) {
767
768         if (getTextWidget() == null || (!redraws() && operation != FORMAT))
769             return;
770
771         switch (operation) {
772             case CONTENTASSIST_PROPOSALS:
773                 fContentAssistant.showPossibleCompletions();
774                 return;
775             case CONTENTASSIST_CONTEXT_INFORMATION:
776                 fContentAssistant.showContextInformation();
777                 return;
778             case QUICK_ASSIST:
779                 // FIXME: must find a way to post to the status line
780
/* String msg= */ fQuickAssistAssistant.showPossibleQuickAssists();
781                 // setStatusLineErrorMessage(msg);
782
return;
783             case INFORMATION:
784                 fInformationPresenter.showInformation();
785                 return;
786             case FORMAT:
787                 {
788                     final Point selection= rememberSelection();
789                     final IRewriteTarget target= getRewriteTarget();
790                     final IDocument document= getDocument();
791                     IFormattingContext context= null;
792                     DocumentRewriteSession rewriteSession= null;
793
794                     if (document instanceof IDocumentExtension4) {
795                         IDocumentExtension4 extension= (IDocumentExtension4) document;
796                         DocumentRewriteSessionType type= selection.y == 0 || selection.y > 1000 ? DocumentRewriteSessionType.SEQUENTIAL : DocumentRewriteSessionType.UNRESTRICTED_SMALL;
797                         rewriteSession= extension.startRewriteSession(type);
798                     } else {
799                         setRedraw(false);
800                         target.beginCompoundChange();
801                     }
802
803                     try {
804
805                         final String JavaDoc rememberedContents= document.get();
806
807                         try {
808
809                             if (fContentFormatter instanceof IContentFormatterExtension) {
810                                 final IContentFormatterExtension extension= (IContentFormatterExtension) fContentFormatter;
811                                 context= createFormattingContext();
812                                 if (selection.y == 0) {
813                                     context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.TRUE);
814                                 } else {
815                                     context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.FALSE);
816                                     context.setProperty(FormattingContextProperties.CONTEXT_REGION, new Region(selection.x, selection.y));
817                                 }
818                                 extension.format(document, context);
819                             } else {
820                                 IRegion r;
821                                 if (selection.y == 0) {
822                                     IRegion coverage= getModelCoverage();
823                                     r= coverage == null ? new Region(0, 0) : coverage;
824                                 } else {
825                                     r= new Region(selection.x, selection.y);
826                                 }
827                                 fContentFormatter.format(document, r);
828                             }
829
830                             updateSlaveDocuments(document);
831
832                         } catch (RuntimeException JavaDoc x) {
833                             // fire wall for https://bugs.eclipse.org/bugs/show_bug.cgi?id=47472
834
// if something went wrong we undo the changes we just did
835
// TODO to be removed after 3.0 M8
836
document.set(rememberedContents);
837                             throw x;
838                         }
839
840                     } finally {
841
842                         if (document instanceof IDocumentExtension4) {
843                             IDocumentExtension4 extension= (IDocumentExtension4) document;
844                             extension.stopRewriteSession(rewriteSession);
845                         } else {
846                             target.endCompoundChange();
847                             setRedraw(true);
848                         }
849
850                         restoreSelection();
851                         if (context != null)
852                             context.dispose();
853                     }
854                     return;
855                 }
856             default:
857                 super.doOperation(operation);
858         }
859     }
860
861     /**
862      * Updates all slave documents of the given document. This default implementation calls <code>updateSlaveDocument</code>
863      * for their current visible range. Subclasses may reimplement.
864      *
865      * @param masterDocument the master document
866      * @since 3.0
867      */

868     protected void updateSlaveDocuments(IDocument masterDocument) {
869         ISlaveDocumentManager manager= getSlaveDocumentManager();
870         if (manager instanceof ISlaveDocumentManagerExtension) {
871             ISlaveDocumentManagerExtension extension= (ISlaveDocumentManagerExtension) manager;
872             IDocument[] slaves= extension.getSlaveDocuments(masterDocument);
873             if (slaves != null) {
874                 for (int i= 0; i < slaves.length; i++) {
875                     if (slaves[i] instanceof ChildDocument) {
876                         ChildDocument child= (ChildDocument) slaves[i];
877                         Position p= child.getParentDocumentRange();
878                         try {
879
880                             if (!updateSlaveDocument(child, p.getOffset(), p.getLength()))
881                                 child.repairLineInformation();
882
883                         } catch (BadLocationException e) {
884                             // ignore
885
}
886                     }
887                 }
888             }
889         }
890     }
891
892     /*
893      * @see ITextOperationTargetExtension#enableOperation(int, boolean)
894      * @since 2.0
895      */

896     public void enableOperation(int operation, boolean enable) {
897
898         switch (operation) {
899             case CONTENTASSIST_PROPOSALS:
900             case CONTENTASSIST_CONTEXT_INFORMATION: {
901
902                 if (fContentAssistant == null)
903                     return;
904
905                 if (enable) {
906                     if (!fContentAssistantInstalled) {
907                         fContentAssistant.install(this);
908                         fContentAssistantInstalled= true;
909                     }
910                 } else if (fContentAssistantInstalled) {
911                     fContentAssistant.uninstall();
912                     fContentAssistantInstalled= false;
913                 }
914                 break;
915             }
916             case QUICK_ASSIST: {
917                 
918                 if (fQuickAssistAssistant == null)
919                     return;
920                 
921                 if (enable) {
922                     if (!fQuickAssistAssistantInstalled) {
923                         fQuickAssistAssistant.install(this);
924                         fQuickAssistAssistantInstalled= true;
925                     }
926                 } else if (fContentAssistantInstalled) {
927                     fQuickAssistAssistant.uninstall();
928                     fContentAssistantInstalled= false;
929                 }
930             }
931         }
932     }
933
934     /*
935      * @see ISourceViewer#setRangeIndicator(Annotation)
936      */

937     public void setRangeIndicator(Annotation rangeIndicator) {
938         fRangeIndicator= rangeIndicator;
939     }
940
941     /*
942      * @see ISourceViewer#setRangeIndication(int, int, boolean)
943      */

944     public void setRangeIndication(int start, int length, boolean moveCursor) {
945
946         if (moveCursor) {
947             setSelectedRange(start, 0);
948             revealRange(start, length);
949         }
950
951         if (fRangeIndicator != null && fVisualAnnotationModel instanceof IAnnotationModelExtension) {
952             IAnnotationModelExtension extension= (IAnnotationModelExtension) fVisualAnnotationModel;
953             extension.modifyAnnotationPosition(fRangeIndicator, new Position(start, length));
954         }
955     }
956
957     /*
958      * @see ISourceViewer#getRangeIndication()
959      */

960     public IRegion getRangeIndication() {
961         if (fRangeIndicator != null && fVisualAnnotationModel != null) {
962             Position position= fVisualAnnotationModel.getPosition(fRangeIndicator);
963             if (position != null)
964                 return new Region(position.getOffset(), position.getLength());
965         }
966
967         return null;
968     }
969
970     /*
971      * @see ISourceViewer#removeRangeIndication()
972      */

973     public void removeRangeIndication() {
974         if (fRangeIndicator != null && fVisualAnnotationModel != null)
975             fVisualAnnotationModel.removeAnnotation(fRangeIndicator);
976     }
977
978     /*
979      * @see ISourceViewer#showAnnotations(boolean)
980      */

981     public void showAnnotations(boolean show) {
982         boolean old= fIsVerticalRulerVisible;
983
984         fIsVerticalRulerVisible= (fVerticalRuler != null && (show || !isVerticalRulerOnlyShowingAnnotations()));
985         if (old != fIsVerticalRulerVisible && fComposite != null && !fComposite.isDisposed())
986             fComposite.layout();
987
988         if (fIsVerticalRulerVisible && show)
989             ensureAnnotationHoverManagerInstalled();
990         else if (fVerticalRulerHoveringController != null) {
991             fVerticalRulerHoveringController.dispose();
992             fVerticalRulerHoveringController= null;
993         }
994     }
995
996     /**
997      * Tells whether the vertical ruler only acts as annotation ruler.
998      *
999      * @return <code>true</code> if the vertical ruler only show annotations
1000     * @since 3.3
1001     */

1002    private boolean isVerticalRulerOnlyShowingAnnotations() {
1003        if (fVerticalRuler instanceof VerticalRuler)
1004            return true;
1005        
1006        if (fVerticalRuler instanceof CompositeRuler) {
1007            Iterator JavaDoc iter= ((CompositeRuler)fVerticalRuler).getDecoratorIterator();
1008            return iter.hasNext() && iter.next() instanceof AnnotationRulerColumn && !iter.hasNext();
1009        }
1010        return false;
1011    }
1012
1013    /**
1014     * Returns the vertical ruler of this viewer.
1015     *
1016     * @return the vertical ruler of this viewer
1017     * @since 3.0
1018     */

1019    protected final IVerticalRuler getVerticalRuler() {
1020        return fVerticalRuler;
1021    }
1022
1023    /*
1024     * @see org.eclipse.jface.text.source.ISourceViewerExtension#showAnnotationsOverview(boolean)
1025     * @since 2.1
1026     */

1027    public void showAnnotationsOverview(boolean show) {
1028        boolean old= fIsOverviewRulerVisible;
1029        fIsOverviewRulerVisible= (show && fOverviewRuler != null);
1030        if (old != fIsOverviewRulerVisible) {
1031            if (fComposite != null && !fComposite.isDisposed())
1032                fComposite.layout();
1033            if (fIsOverviewRulerVisible) {
1034                ensureOverviewHoverManagerInstalled();
1035            } else if (fOverviewRulerHoveringController != null) {
1036                fOverviewRulerHoveringController.dispose();
1037                fOverviewRulerHoveringController= null;
1038            }
1039        }
1040    }
1041    
1042    /*
1043     * @see org.eclipse.jface.text.source.ISourceViewer#getCurrentAnnotationHover()
1044     * @since 3.2
1045     */

1046    public IAnnotationHover getCurrentAnnotationHover() {
1047        if (fVerticalRulerHoveringController == null)
1048            return null;
1049        return fVerticalRulerHoveringController.getCurrentAnnotationHover();
1050    }
1051}
1052
Popular Tags