OSDN Git Service

2004-11-30 Thomas Fitzsimmons <fitzsim@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / javax / swing / border / MatteBorder.java
1 /* MatteBorder.java -- 
2    Copyright (C) 2003, 2004  Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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.
10
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.
15
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
20
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.
25
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. */
37
38
39 package javax.swing.border;
40
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Graphics;
44 import java.awt.Insets;
45
46 import javax.swing.Icon;
47
48 /**
49  * A border that is filled with either a solid color or with repeated
50  * icon tiles.
51  *
52  * <p><img src="doc-files/MatteBorder-1.png" width="500" height="150"
53  * alt="[Two MatteBorders]" />
54  *
55  * @author Sascha Brawer (brawer@dandelis.ch)
56  */
57 public class MatteBorder
58   extends EmptyBorder
59 {
60   /**
61    * Determined using the <code>serialver</code> tool
62    * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
63    */
64   static final long serialVersionUID = 4422248989617298224L;
65   
66   
67   /**
68    * The color that is used for filling the border, or
69    * <code>null</code> if the border is filled with repetitions of a
70    * tile icon.
71    *
72    * @see #tileIcon
73    */
74   protected Color color;
75   
76   
77   /**
78    * The icon is used for filling the border with a tile, or
79    * <code>null</code> if the border is filled with a solid
80    * color.
81    *
82    * @see #color
83    */
84   protected Icon tileIcon;
85   
86   
87   /**
88    * Constructs a MatteBorder given the width on each side
89    * and a fill color.
90    *
91    * <p><img src="doc-files/MatteBorder-2.png" width="500" height="150"
92    * alt="[A picture of a MatteBorder made by this constructor]" />
93    *
94    * @param top the width of the border at its top edge.
95    * @param left the width of the border at its left edge.
96    * @param bottom the width of the border at its bottom edge.
97    * @param right the width of the border at its right edge.
98    * @param matteColor the color for filling the border.
99    */
100   public MatteBorder(int top, int left, int bottom, int right,
101                      Color matteColor)
102   {
103     super(top, left, bottom, right);
104
105     if (matteColor == null)
106       throw new IllegalArgumentException();
107
108     this.color = matteColor;
109   }
110
111
112   /**
113    * Constructs a MatteBorder given its insets and fill color.
114    *
115    * <p><img src="doc-files/MatteBorder-3.png" width="500" height="150"
116    * alt="[A picture of a MatteBorder made by this constructor]" />
117    *
118    * @param borderInsets an Insets object whose <code>top</code>,
119    *        <code>left</code>, <code>bottom</code> and <code>right</code>
120    *        fields indicate the with of the border at the respective
121    *        edge.
122    *
123    * @param matteColor the color for filling the border.
124    */
125   public MatteBorder(Insets borderInsets, Color matteColor)
126   {
127     this(borderInsets.top, borderInsets.left,
128          borderInsets.bottom, borderInsets.right,
129          matteColor);
130   }
131
132
133   /**
134    * Constructs a MatteBorder given the width on each side
135    * and an icon for tiling the border area.
136    *
137    * <p><img src="doc-files/MatteBorder-4.png" width="500" height="150"
138    * alt="[A picture of a MatteBorder made by this constructor]" />
139    *
140    * @param top the width of the border at its top edge.
141    * @param left the width of the border at its left edge.
142    * @param bottom the width of the border at its bottom edge.
143    * @param right the width of the border at its right edge.
144    * @param tileIcon an icon for tiling the border area.
145    */
146   public MatteBorder(int top, int left, int bottom, int right,
147                      Icon tileIcon)
148   {
149     super(top, left, bottom, right);
150
151     if (tileIcon == null)
152       throw new IllegalArgumentException();
153
154     this.tileIcon = tileIcon;
155   }
156
157
158   /**
159    * Constructs a MatteBorder given its insets and an icon
160    * for tiling the border area.
161    *
162    * <p><img src="doc-files/MatteBorder-5.png" width="500" height="150"
163    * alt="[A picture of a MatteBorder made by this constructor]" />
164    *
165    * @param borderInsets an Insets object whose <code>top</code>,
166    *        <code>left</code>, <code>bottom</code> and <code>right</code>
167    *        fields indicate the with of the border at the respective
168    *        edge.
169    *
170    * @param tileIcon an icon for tiling the border area.
171    */
172   public MatteBorder(Insets borderInsets, Icon tileIcon)
173   {
174     this(borderInsets.top, borderInsets.left,
175          borderInsets.bottom, borderInsets.right,
176          tileIcon);
177   }
178   
179   
180   /**
181    * Constructs a MatteBorder given an icon for tiling the
182    * border area. The icon width is used for the border insets
183    * at the left and right edge, the icon height for the top and
184    * bottom edge.
185    *
186    * <p><img src="doc-files/MatteBorder-6.png" width="379" height="150"
187    * alt="[A picture of a MatteBorder made by this constructor]" />
188    *
189    * @param tileIcon an icon for tiling the border area.
190    */
191   public MatteBorder(Icon tileIcon)
192   {
193     this(-1, -1, -1, -1, tileIcon);
194   }
195   
196   
197   /**
198    * Paints the border for a given component.
199    *
200    * @param c the component whose border is to be painted.
201    * @param g the graphics for painting.
202    * @param x the horizontal position for painting the border.
203    * @param y the vertical position for painting the border.
204    * @param width the width of the available area for painting the border.
205    * @param height the height of the available area for painting the border.
206    */
207   public void paintBorder(Component c, Graphics  g,
208                           int x, int y, int width, int height)
209   {
210     Insets i = getBorderInsets();
211     paintEdge(c, g, x, y, width, i.top, 0, 0);      // top edge
212     paintEdge(c, g, x, y + height - i.bottom,       // bottom edge
213               width, i.bottom,
214               0, height - i.bottom);
215     paintEdge(c, g, x, y + i.top,                   // left edge
216               i.left, height - i.top,
217               0, i.top);
218     paintEdge(c, g, x + width - i.right, y + i.top, // right edge
219               i.right, height - i.bottom,
220               width - i.right, i.top);
221   }
222   
223   
224   /**
225    * Measures the width of this border.
226    *
227    * @param c the component whose border is to be measured.
228    *
229    * @return an Insets object whose <code>left</code>, <code>right</code>,
230    *         <code>top</code> and <code>bottom</code> fields indicate the
231    *         width of the border at the respective edge.
232    *
233    * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
234    */
235   public Insets getBorderInsets(Component c)
236   {
237     /* There is no obvious reason for overriding this method, but we
238      * try to have exactly the same API as the Sun reference
239      * implementation.
240      */
241     return this.getBorderInsets(c, null);
242   }
243   
244   
245   /**
246    * Measures the width of this border, storing the results into a
247    * pre-existing Insets object.
248    *
249    * @param insets an Insets object for holding the result values.
250    *        After invoking this method, the <code>left</code>,
251    *        <code>right</code>, <code>top</code> and
252    *        <code>bottom</code> fields indicate the width of the
253    *        border at the respective edge.
254    *
255    * @return the same object that was passed for <code>insets</code>.
256    *
257    * @see #getBorderInsets()
258    */
259   public Insets getBorderInsets(Component c, Insets insets)
260   {
261     if (insets == null)
262       insets = new Insets(0, 0, 0, 0);
263
264     if ((tileIcon != null)
265         && (top < 0) && (left < 0)
266         && (right < 0) && (bottom < 0))
267     {
268       insets.left = insets.right = tileIcon.getIconWidth();
269       insets.top = insets.bottom = tileIcon.getIconHeight();
270       return insets;
271     }
272
273     /* Copy top, left, bottom and right into the respective
274      * field of insets.
275      */
276     return super.getBorderInsets(c, insets);
277   }
278   
279   
280   /**
281    * Measures the width of this border.
282    *
283    * @return an Insets object whose <code>left</code>, <code>right</code>,
284    *         <code>top</code> and <code>bottom</code> fields indicate the
285    *         width of the border at the respective edge.
286    *
287    * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
288    */
289   public Insets getBorderInsets()
290   {
291     /* The inherited implementation of EmptyBorder.isBorderOpaque()
292      * would do the same. It is not clear why this is overriden in the
293      * Sun implementation, at least not from just reading the JavaDoc.
294      */
295     return this.getBorderInsets(null, null);
296   }
297   
298   
299   /**
300    * Returns the color that is used for filling the border, or
301    * <code>null</code> if the border is filled with repetitions of a
302    * tile icon.
303    */
304   public Color getMatteColor()
305   {
306     return color;
307   }
308   
309   
310   /**
311    * Returns the icon is used for tiling the border, or
312    * <code>null</code> if the border is filled with a color instead of
313    * an icon.
314    */
315   public Icon getTileIcon()
316   {
317     return tileIcon;
318   }
319   
320   
321   /**
322    * Determines whether this border fills every pixel in its area
323    * when painting.
324    *
325    * @return <code>true</code> if the border is filled with an
326    *         opaque color; <code>false</code> if it is filled with
327    *         a semi-transparent color or with an icon.
328    */
329   public boolean isBorderOpaque()
330   {
331     return (color != null) && (color.getAlpha() == 255);
332   }
333   
334
335   /**
336    * Paints a rectangular area of the border. This private helper
337    * method is called once for each of the border edges
338    * by {@link #paintBorder}.
339    *
340    * @param c the component whose border is being painted.
341    * @param g the graphics for painting.
342    * @param x the horizontal position of the rectangular area.
343    * @param y the vertical position of the rectangular area.
344    * @param width the width of the rectangular area.
345    * @param height the height of the rectangular area.
346    * @param dx the x displacement for repeating the tile.
347    * @param dy the y displacement for repeating the tile.
348    */
349   private void paintEdge(Component c, Graphics g,
350                          int x, int y, int width, int height,
351                          int dx, int dy)
352   {
353     Color oldColor;
354     int iconWidth, iconHeight;
355     Graphics clipped;
356
357     if ((width <= 0) || (height <= 0))
358       return;
359
360     /* Paint a colored rectangle if desired. */
361     if (color != null)
362     {
363       oldColor = g.getColor();
364       try
365       {
366         g.setColor(color);
367         g.fillRect(x, y, width, height);
368       }
369       finally
370       {
371         g.setColor(oldColor);
372       }
373       return;
374     }
375
376     /* Determine the width and height of the icon. Some icons return
377      * -1 if it is an image whose dimensions have not yet been
378      * retrieved. There is not much we can do about this, but we
379      * should at least avoid entering the paint loop below
380      * with negative increments.
381      */
382     iconWidth = tileIcon.getIconWidth();
383     iconHeight = tileIcon.getIconHeight();
384     if ((iconWidth <= 0) || (iconHeight <= 0))
385       return;
386
387     dx = dx % iconWidth;
388     dy = dy % iconHeight;
389
390     clipped = g.create();
391     try
392     {
393       clipped.setClip(x, y, width, height);
394       for (int ty = y - dy; ty < y + height; ty += iconHeight)
395         for (int tx = x - dx; tx < x + width; tx += iconWidth)
396           tileIcon.paintIcon(c, clipped, tx, ty);
397     }
398     finally
399     {
400       clipped.dispose();
401     }
402   }
403 }
404