KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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
14 import org.eclipse.swt.custom.StyledText;
15 import org.eclipse.swt.events.PaintEvent;
16 import org.eclipse.swt.events.PaintListener;
17 import org.eclipse.swt.graphics.Color;
18 import org.eclipse.swt.graphics.GC;
19 import org.eclipse.swt.graphics.Point;
20 import org.eclipse.swt.graphics.Rectangle;
21
22 import org.eclipse.jface.text.BadLocationException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IPaintPositionManager;
25 import org.eclipse.jface.text.IPainter;
26 import org.eclipse.jface.text.IRegion;
27 import org.eclipse.jface.text.ITextViewerExtension5;
28 import org.eclipse.jface.text.Position;
29 import org.eclipse.jface.text.Region;
30
31 /**
32  * Highlights the peer character matching the character near the caret position.
33  * This painter can be configured with an
34  * {@link org.eclipse.jface.text.source.ICharacterPairMatcher}.
35  * <p>
36  * Clients instantiate and configure object of this class.</p>
37  *
38  * @since 2.1
39  */

40 public final class MatchingCharacterPainter implements IPainter, PaintListener {
41
42     /** Indicates whether this painter is active */
43     private boolean fIsActive= false;
44     /** The source viewer this painter is associated with */
45     private ISourceViewer fSourceViewer;
46     /** The viewer's widget */
47     private StyledText fTextWidget;
48     /** The color in which to highlight the peer character */
49     private Color fColor;
50     /** The paint position manager */
51     private IPaintPositionManager fPaintPositionManager;
52     /** The strategy for finding matching characters */
53     private ICharacterPairMatcher fMatcher;
54     /** The position tracking the matching characters */
55     private Position fPairPosition= new Position(0, 0);
56     /** The anchor indicating whether the character is left or right of the caret */
57     private int fAnchor;
58
59
60     /**
61      * Creates a new MatchingCharacterPainter for the given source viewer using
62      * the given character pair matcher. The character matcher is not adopted by
63      * this painter. Thus, it is not disposed. However, this painter requires
64      * exclusive access to the given pair matcher.
65      *
66      * @param sourceViewer
67      * @param matcher
68      */

69     public MatchingCharacterPainter(ISourceViewer sourceViewer, ICharacterPairMatcher matcher) {
70         fSourceViewer= sourceViewer;
71         fMatcher= matcher;
72         fTextWidget= sourceViewer.getTextWidget();
73     }
74
75     /**
76      * Sets the color in which to highlight the match character.
77      *
78      * @param color the color
79      */

80     public void setColor(Color color) {
81         fColor= color;
82     }
83
84     /*
85      * @see org.eclipse.jface.text.IPainter#dispose()
86      */

87     public void dispose() {
88         if (fMatcher != null) {
89             fMatcher.clear();
90             fMatcher= null;
91         }
92
93         fColor= null;
94         fTextWidget= null;
95     }
96
97     /*
98      * @see org.eclipse.jface.text.IPainter#deactivate(boolean)
99      */

100     public void deactivate(boolean redraw) {
101         if (fIsActive) {
102             fIsActive= false;
103             fTextWidget.removePaintListener(this);
104             if (fPaintPositionManager != null)
105                 fPaintPositionManager.unmanagePosition(fPairPosition);
106             if (redraw)
107                 handleDrawRequest(null);
108         }
109     }
110
111     /*
112      * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
113      */

114     public void paintControl(PaintEvent event) {
115         if (fTextWidget != null)
116             handleDrawRequest(event.gc);
117     }
118
119     /**
120      * Handles a redraw request.
121      *
122      * @param gc the GC to draw into.
123      */

124     private void handleDrawRequest(GC gc) {
125
126         if (fPairPosition.isDeleted)
127             return;
128
129         int offset= fPairPosition.getOffset();
130         int length= fPairPosition.getLength();
131         if (length < 1)
132             return;
133
134         if (fSourceViewer instanceof ITextViewerExtension5) {
135             ITextViewerExtension5 extension= (ITextViewerExtension5) fSourceViewer;
136             IRegion widgetRange= extension.modelRange2WidgetRange(new Region(offset, length));
137             if (widgetRange == null)
138                 return;
139
140             try {
141                 // don't draw if the pair position is really hidden and widgetRange just
142
// marks the coverage around it.
143
IDocument doc= fSourceViewer.getDocument();
144                 int startLine= doc.getLineOfOffset(offset);
145                 int endLine= doc.getLineOfOffset(offset + length);
146                 if (extension.modelLine2WidgetLine(startLine) == -1 || extension.modelLine2WidgetLine(endLine) == -1)
147                     return;
148             } catch (BadLocationException e) {
149                 return;
150             }
151
152             offset= widgetRange.getOffset();
153             length= widgetRange.getLength();
154
155         } else {
156             IRegion region= fSourceViewer.getVisibleRegion();
157             if (region.getOffset() > offset || region.getOffset() + region.getLength() < offset + length)
158                 return;
159             offset -= region.getOffset();
160         }
161
162         if (ICharacterPairMatcher.RIGHT == fAnchor)
163             draw(gc, offset, 1);
164         else
165             draw(gc, offset + length -1, 1);
166     }
167
168     /**
169      * Highlights the given widget region.
170      *
171      * @param gc the GC to draw into
172      * @param offset the offset of the widget region
173      * @param length the length of the widget region
174      */

175     private void draw(GC gc, int offset, int length) {
176         if (gc != null) {
177
178             gc.setForeground(fColor);
179             
180             Rectangle bounds;
181             if (length > 0)
182                 bounds= fTextWidget.getTextBounds(offset, offset + length - 1);
183             else {
184                 Point loc= fTextWidget.getLocationAtOffset(offset);
185                 bounds= new Rectangle(loc.x, loc.y, 1, fTextWidget.getLineHeight(offset));
186             }
187             
188             // draw box around line segment
189
gc.drawRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);
190
191             // draw box around character area
192
// int widgetBaseline= fTextWidget.getBaseline();
193
// FontMetrics fm= gc.getFontMetrics();
194
// int fontBaseline= fm.getAscent() + fm.getLeading();
195
// int fontBias= widgetBaseline - fontBaseline;
196

197 // gc.drawRectangle(left.x, left.y + fontBias, right.x - left.x - 1, fm.getHeight() - 1);
198

199         } else {
200             fTextWidget.redrawRange(offset, length, true);
201         }
202     }
203
204     /*
205      * @see org.eclipse.jface.text.IPainter#paint(int)
206      */

207     public void paint(int reason) {
208
209         IDocument document= fSourceViewer.getDocument();
210         if (document == null) {
211             deactivate(false);
212             return;
213         }
214
215         Point selection= fSourceViewer.getSelectedRange();
216         if (selection.y > 0) {
217             deactivate(true);
218             return;
219         }
220
221         IRegion pair= fMatcher.match(document, selection.x);
222         if (pair == null) {
223             deactivate(true);
224             return;
225         }
226
227         if (fIsActive) {
228
229             if (IPainter.CONFIGURATION == reason) {
230
231                 // redraw current highlighting
232
handleDrawRequest(null);
233
234             } else if (pair.getOffset() != fPairPosition.getOffset() ||
235                     pair.getLength() != fPairPosition.getLength() ||
236                     fMatcher.getAnchor() != fAnchor) {
237
238                 // otherwise only do something if position is different
239

240                 // remove old highlighting
241
handleDrawRequest(null);
242                 // update position
243
fPairPosition.isDeleted= false;
244                 fPairPosition.offset= pair.getOffset();
245                 fPairPosition.length= pair.getLength();
246                 fAnchor= fMatcher.getAnchor();
247                 // apply new highlighting
248
handleDrawRequest(null);
249
250             }
251         } else {
252
253             fIsActive= true;
254
255             fPairPosition.isDeleted= false;
256             fPairPosition.offset= pair.getOffset();
257             fPairPosition.length= pair.getLength();
258             fAnchor= fMatcher.getAnchor();
259
260             fTextWidget.addPaintListener(this);
261             fPaintPositionManager.managePosition(fPairPosition);
262             handleDrawRequest(null);
263         }
264     }
265
266     /*
267      * @see org.eclipse.jface.text.IPainter#setPositionManager(org.eclipse.jface.text.IPaintPositionManager)
268      */

269     public void setPositionManager(IPaintPositionManager manager) {
270         fPaintPositionManager= manager;
271     }
272 }
273
Popular Tags