Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / javax / swing / text / DefaultHighlighter.java
blob59f77316e87f6a833e17a3a0e79cf8c89b3ff42f
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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
56 extends LayerPainter
58 private Color color;
60 public DefaultHighlightPainter(Color c)
62 super();
63 color = c;
66 public Color getColor()
68 return color;
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,
77 JTextComponent t)
79 if (p0 == p1)
80 return;
82 Rectangle rect = bounds.getBounds();
84 if (color == null)
85 g.setColor(t.getSelectionColor());
86 else
87 g.setColor(color);
89 TextUI ui = t.getUI();
91 try
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.
100 if (l0.y == l1.y)
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);
109 else
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
115 // out the bounds.
116 // 3. The final line is painted from the left border to the
117 // position of p1.
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.
122 l0.x -= rect.x;
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);
129 if (posBelow != -1
130 && posBelow != p0
131 && Utilities.getRowStart(t, posBelow)
132 != p1RowStart)
134 Rectangle grow = ui.modelToView(t, posBelow);
135 grow.x = rect.x;
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)
147 break;
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;
163 l1.x = rect.x;
164 paintHighlight(g, l1);
167 catch (BadLocationException ex)
169 AssertionError err = new AssertionError("Unexpected bad location exception");
170 err.initCause(ex);
171 throw err;
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
184 int p0;
185 int p1;
186 Highlighter.HighlightPainter painter;
188 public HighlightEntry(int p0, int p1, Highlighter.HighlightPainter painter)
190 this.p0 = p0;
191 this.p1 = p1;
192 this.painter = painter;
195 public int getStartOffset()
197 return p0;
200 public int getEndOffset()
202 return p1;
205 public Highlighter.HighlightPainter getPainter()
207 return painter;
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
239 if (p0 < 0)
240 throw new BadLocationException("DefaultHighlighter", p0);
242 if (p1 < p0)
243 throw new BadLocationException("DefaultHighlighter", p1);
246 public void install(JTextComponent c)
248 textComponent = 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);
266 return entry;
269 public void removeHighlight(Object tag)
271 highlights.remove(tag);
273 HighlightEntry entry = (HighlightEntry) tag;
274 textComponent.getUI().damageRange(textComponent,
275 entry.p0,
276 entry.p1);
279 public void removeAllHighlights()
281 highlights.clear();
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
293 int o0, o1;
295 checkPositions(n0, n1);
296 HighlightEntry entry = (HighlightEntry) tag;
297 o0 = entry.p0;
298 o1 = entry.p1;
300 // Prevent useless write & repaint operations.
301 if (o0 == n0 && o1 == n1)
302 return;
304 entry.p0 = n0;
305 entry.p1 = n1;
307 TextUI ui = textComponent.getUI();
309 // Special situation where the old area has to be cleared simply.
310 if (n0 == n1)
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
318 int fds, sds;
319 int fde, sde;
321 // Calculate first damaged region.
322 if(o0 < n0)
324 // Damaged region will be cleared as
325 // the old highlight region starts first.
326 fds = o0;
327 fde = n0;
329 else
331 // Damaged region will be painted as
332 // the new highlight region starts first.
333 fds = n0;
334 fde = o0;
337 if (o1 < n1)
339 // Final region will be painted as the
340 // old highlight region finishes first
341 sds = o1;
342 sde = n1;
344 else
346 // Final region will be cleared as the
347 // new highlight region finishes first.
348 sds = n1;
349 sde = o1;
352 // If there is no undamaged region in between
353 // call damageRange only once.
354 if (fde == sds)
355 ui.damageRange(textComponent, fds, sde);
356 else
358 if (fds != fde)
359 ui.damageRange(textComponent, fds, fde);
361 if (sds != sde)
362 ui.damageRange(textComponent, sds, sde);
365 else
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,
377 View view)
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.
388 if (size == 0)
389 return;
391 // Prepares the rectangle of the inner drawing area.
392 Insets insets = textComponent.getInsets();
393 Shape bounds =
394 new Rectangle(insets.left,
395 insets.top,
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);