1 /* DefaultHighlighter.java --
2 Copyright (C) 2004, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax
.swing
.text
;
41 import gnu
.classpath
.NotImplementedException
;
43 import java
.awt
.Color
;
44 import java
.awt
.Graphics
;
45 import java
.awt
.Insets
;
46 import java
.awt
.Rectangle
;
47 import java
.awt
.Shape
;
48 import java
.util
.ArrayList
;
50 import javax
.swing
.SwingUtilities
;
51 import javax
.swing
.plaf
.TextUI
;
53 public class DefaultHighlighter
extends LayeredHighlighter
55 public static class DefaultHighlightPainter
60 public DefaultHighlightPainter(Color c
)
66 public Color
getColor()
71 private void paintHighlight(Graphics g
, Rectangle rect
)
73 g
.fillRect(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
76 public void paint(Graphics g
, int p0
, int p1
, Shape bounds
,
82 Rectangle rect
= bounds
.getBounds();
85 g
.setColor(t
.getSelectionColor());
89 TextUI ui
= t
.getUI();
94 Rectangle l0
= ui
.modelToView(t
, p0
, null);
95 Rectangle l1
= ui
.modelToView(t
, p1
, null);
97 // Note: The computed locations may lie outside of the allocation
98 // area if the text is scrolled.
102 SwingUtilities
.computeUnion(l0
.x
, l0
.y
, l0
.width
, l0
.height
, l1
);
104 // Paint only inside the allocation area.
105 SwingUtilities
.computeIntersection(rect
.x
, rect
.y
, rect
.width
, rect
.height
, l1
);
107 paintHighlight(g
, l1
);
111 // 1. The line of p0 is painted from the position of p0
112 // to the right border.
113 // 2. All lines between the ones where p0 and p1 lie on
114 // are completely highlighted. The allocation area is used to find
116 // 3. The final line is painted from the left border to the
119 // Highlight first line until the end.
120 // If rect.x is non-zero the calculation will properly adjust the
121 // area to be painted.
123 l0
.width
= rect
.width
- l0
.x
- rect
.x
;
125 paintHighlight(g
, l0
);
127 int posBelow
= Utilities
.getPositionBelow(t
, p0
, l0
.x
);
128 int p1RowStart
= Utilities
.getRowStart(t
, p1
);
131 && Utilities
.getRowStart(t
, posBelow
)
134 Rectangle grow
= ui
.modelToView(t
, posBelow
);
136 grow
.width
= rect
.width
;
138 // Find further lines which have to be highlighted completely.
139 int nextPosBelow
= posBelow
;
140 while (nextPosBelow
!= -1
141 && Utilities
.getRowStart(t
, nextPosBelow
) != p1RowStart
)
143 posBelow
= nextPosBelow
;
144 nextPosBelow
= Utilities
.getPositionBelow(t
, posBelow
, l0
.x
);
146 if (nextPosBelow
== posBelow
)
149 // Now posBelow is an offset on the last line which has to be painted
150 // completely. (newPosBelow is on the same line as p1)
152 // Retrieve the rectangle of posBelow and use its y and height
153 // value to calculate the final height of the multiple line
154 // spanning rectangle.
155 Rectangle end
= ui
.modelToView(t
, posBelow
);
156 grow
.height
= end
.y
+ end
.height
- grow
.y
;
158 paintHighlight(g
, grow
);
161 // Paint last line from its beginning to the position of p1.
162 l1
.width
= l1
.x
+ l1
.width
- rect
.x
;
164 paintHighlight(g
, l1
);
167 catch (BadLocationException ex
)
169 AssertionError err
= new AssertionError("Unexpected bad location exception");
175 public Shape
paintLayer(Graphics g
, int p0
, int p1
, Shape bounds
,
176 JTextComponent c
, View view
)
178 throw new InternalError();
182 private class HighlightEntry
implements Highlighter
.Highlight
186 Highlighter
.HighlightPainter painter
;
188 public HighlightEntry(int p0
, int p1
, Highlighter
.HighlightPainter painter
)
192 this.painter
= painter
;
195 public int getStartOffset()
200 public int getEndOffset()
205 public Highlighter
.HighlightPainter
getPainter()
212 * @specnote final as of 1.4
214 public static final LayeredHighlighter
.LayerPainter DefaultPainter
=
215 new DefaultHighlightPainter(null);
217 private JTextComponent textComponent
;
218 private ArrayList highlights
= new ArrayList();
219 private boolean drawsLayeredHighlights
= true;
221 public DefaultHighlighter()
223 // Nothing to do here.
226 public boolean getDrawsLayeredHighlights()
228 return drawsLayeredHighlights
;
231 public void setDrawsLayeredHighlights(boolean newValue
)
233 drawsLayeredHighlights
= newValue
;
236 private void checkPositions(int p0
, int p1
)
237 throws BadLocationException
240 throw new BadLocationException("DefaultHighlighter", p0
);
243 throw new BadLocationException("DefaultHighlighter", p1
);
246 public void install(JTextComponent c
)
249 removeAllHighlights();
252 public void deinstall(JTextComponent c
)
254 textComponent
= null;
257 public Object
addHighlight(int p0
, int p1
, Highlighter
.HighlightPainter painter
)
258 throws BadLocationException
260 checkPositions(p0
, p1
);
261 HighlightEntry entry
= new HighlightEntry(p0
, p1
, painter
);
262 highlights
.add(entry
);
264 textComponent
.getUI().damageRange(textComponent
, p0
, p1
);
269 public void removeHighlight(Object tag
)
271 highlights
.remove(tag
);
273 HighlightEntry entry
= (HighlightEntry
) tag
;
274 textComponent
.getUI().damageRange(textComponent
,
279 public void removeAllHighlights()
284 public Highlighter
.Highlight
[] getHighlights()
286 return (Highlighter
.Highlight
[])
287 highlights
.toArray(new Highlighter
.Highlight
[highlights
.size()]);
290 public void changeHighlight(Object tag
, int n0
, int n1
)
291 throws BadLocationException
295 checkPositions(n0
, n1
);
296 HighlightEntry entry
= (HighlightEntry
) tag
;
300 // Prevent useless write & repaint operations.
301 if (o0
== n0
&& o1
== n1
)
307 TextUI ui
= textComponent
.getUI();
309 // Special situation where the old area has to be cleared simply.
311 ui
.damageRange(textComponent
, o0
, o1
);
312 // Calculates the areas where a change is really neccessary
313 else if ((o1
> n0
&& o1
<= n1
)
314 || (n1
> o0
&& n1
<= o1
))
316 // [fds, fde) - the first damage region
317 // [sds, sde] - the second damage region
321 // Calculate first damaged region.
324 // Damaged region will be cleared as
325 // the old highlight region starts first.
331 // Damaged region will be painted as
332 // the new highlight region starts first.
339 // Final region will be painted as the
340 // old highlight region finishes first
346 // Final region will be cleared as the
347 // new highlight region finishes first.
352 // If there is no undamaged region in between
353 // call damageRange only once.
355 ui
.damageRange(textComponent
, fds
, sde
);
359 ui
.damageRange(textComponent
, fds
, fde
);
362 ui
.damageRange(textComponent
, sds
, sde
);
367 // The two regions do not overlap. So mark
368 // both areas as damaged.
369 ui
.damageRange(textComponent
, o0
, o1
);
370 ui
.damageRange(textComponent
, n0
, n1
);
375 public void paintLayeredHighlights(Graphics g
, int p0
, int p1
,
376 Shape viewBounds
, JTextComponent editor
,
378 throws NotImplementedException
380 // TODO: Implement this properly.
383 public void paint(Graphics g
)
385 int size
= highlights
.size();
387 // Check if there are any highlights.
391 // Prepares the rectangle of the inner drawing area.
392 Insets insets
= textComponent
.getInsets();
394 new Rectangle(insets
.left
,
396 textComponent
.getWidth() - insets
.left
- insets
.right
,
397 textComponent
.getHeight() - insets
.top
- insets
.bottom
);
399 for (int index
= 0; index
< size
; ++index
)
401 HighlightEntry entry
= (HighlightEntry
) highlights
.get(index
);
402 entry
.painter
.paint(g
, entry
.p0
, entry
.p1
, bounds
, textComponent
);