001 /* CompoundBorder.java --
002 Copyright (C) 2003 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.swing.border;
040
041 import java.awt.Component;
042 import java.awt.Graphics;
043 import java.awt.Insets;
044
045 /**
046 * A Border that is composed of an interior and an exterior border,
047 * where the interior border is tightly nested into the exterior.
048 *
049 * @author Sascha Brawer (brawer@dandelis.ch)
050 */
051 public class CompoundBorder extends AbstractBorder
052 {
053 /**
054 * Determined using the <code>serialver</code> tool
055 * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
056 */
057 static final long serialVersionUID = 9054540377030555103L;
058
059 /**
060 * The inside border, which is painted between the bordered
061 * Component and the outside border. It is valid for
062 * <code>insideBorder</code> to be <code>null</code>.
063 */
064 protected Border insideBorder;
065
066 /**
067 * The outside border, which is painted outside both the
068 * bordered Component and the inside border. It is valid for
069 * <code>outsideBorder</code> to be <code>null</code>.
070 */
071 protected Border outsideBorder;
072
073 /**
074 * Constructs a CompoundBorder whose inside and outside borders
075 * are both <code>null</code>. While this does not really make
076 * any sense (there exists a class EmptyBorder as well, and not
077 * every Component needs to have a border at all), the API
078 * specification requires the existence of this constructor.
079 *
080 * @see EmptyBorder
081 */
082 public CompoundBorder()
083 {
084 this (null, null);
085 }
086
087 /**
088 * Constructs a CompoundBorder with the specified inside and
089 * outside borders.
090 *
091 * @param outsideBorder the outside border, which is painted to the
092 * outside of both <code>insideBorder</code> and the enclosed
093 * component. It is acceptable to pass <code>null</code>, in
094 * which case no outside border is painted.
095 *
096 * @param insideBorder the inside border, which is painted to
097 * between <code>outsideBorder</code> and the enclosed
098 * component. It is acceptable to pass <code>null</code>, in
099 * which case no inside border is painted.
100 */
101 public CompoundBorder(Border outsideBorder, Border insideBorder)
102 {
103 this.outsideBorder = outsideBorder;
104 this.insideBorder = insideBorder;
105 }
106
107 /**
108 * Determines whether or not this border is opaque. An opaque
109 * border fills every pixel in its area when painting. Partially
110 * translucent borders must return <code>false</code>, or ugly
111 * artifacts can appear on screen.
112 *
113 * @return <code>true</code> if both the inside and outside borders
114 * are opaque, or <code>false</code> otherwise.
115 */
116 public boolean isBorderOpaque()
117 {
118 // Although the API specification states that this method
119 // returns true if both the inside and outside borders are non-null
120 // and opaque, and false otherwise, a mauve test shows that if both
121 // the inside or outside borders are null, then true is returned.
122 if ((insideBorder == null) && (outsideBorder == null))
123 return true;
124
125 // A mauve test shows that if the inside border has a null value,
126 // then true is returned if the outside border is opaque; if the
127 // outside border has a null value, then true is returned if the
128 // inside border is opaque; else, true is returned if both the
129 // inside and outside borders are opaque.
130 if (insideBorder == null)
131 return outsideBorder.isBorderOpaque();
132 else if (outsideBorder == null)
133 return insideBorder.isBorderOpaque();
134 else
135 return insideBorder.isBorderOpaque() && outsideBorder.isBorderOpaque();
136 }
137
138 /**
139 * Paints the compound border by first painting the outside border,
140 * then painting the inside border tightly nested into the outside.
141 *
142 * @param c the component whose border is to be painted.
143 * @param g the graphics for painting.
144 * @param x the horizontal position for painting the border.
145 * @param y the vertical position for painting the border.
146 * @param width the width of the available area for painting the border.
147 * @param height the height of the available area for painting the border.
148 */
149 public void paintBorder(Component c, Graphics g,
150 int x, int y, int width, int height)
151 {
152 // If there is an outside border, paint it and reduce the
153 // bounding box by its insets.
154 //
155 if (outsideBorder != null)
156 {
157 Insets outsideInsets;
158
159 outsideBorder.paintBorder(c, g, x, y, width, height);
160 outsideInsets = outsideBorder.getBorderInsets(c);
161
162 x += outsideInsets.left;
163 y += outsideInsets.top;
164
165 // Reduce width and height by the respective extent of the
166 // outside border.
167 width -= outsideInsets.left + outsideInsets.right;
168 height -= outsideInsets.top + outsideInsets.bottom;
169 }
170
171 if (insideBorder != null)
172 insideBorder.paintBorder(c, g, x, y, width, height);
173 }
174
175 /**
176 * Changes the specified insets to the insets of this border,
177 * which is the sum of the insets of the inside and the outside
178 * border.
179 *
180 * @param c the component in the center of this border.
181 * @param insets an Insets object for holding the added insets.
182 *
183 * @return the <code>insets</code> object.
184 */
185 public Insets getBorderInsets(Component c, Insets insets)
186 {
187 Insets borderInsets;
188
189 if (insets == null)
190 insets = new Insets(0, 0, 0, 0);
191 else
192 insets.left = insets.right = insets.top = insets.bottom = 0;
193
194 // If there is an outside border, add it to insets.
195 if (outsideBorder != null)
196 {
197 borderInsets = outsideBorder.getBorderInsets(c);
198 insets.left += borderInsets.left;
199 insets.right += borderInsets.right;
200 insets.top += borderInsets.top;
201 insets.bottom += borderInsets.bottom;
202 }
203
204 // If there is an inside border, add it to insets.
205 if (insideBorder != null)
206 {
207 borderInsets = insideBorder.getBorderInsets(c);
208 insets.left += borderInsets.left;
209 insets.right += borderInsets.right;
210 insets.top += borderInsets.top;
211 insets.bottom += borderInsets.bottom;
212 }
213
214 return insets;
215 }
216
217 /**
218 * Determines the insets of this border, which is the sum of the
219 * insets of the inside and the outside border.
220 *
221 * @param c the component in the center of this border.
222 */
223 public Insets getBorderInsets(Component c)
224 {
225 // It is not clear why CompoundBorder does not simply inherit
226 // the implementation from AbstractBorder. However, we want
227 // to be compatible with the API specification, which overrides
228 // the getBorderInsets(Component) method.
229 return getBorderInsets(c, null);
230 }
231
232 /**
233 * Returns the outside border, which is painted outside both the
234 * bordered Component and the inside border. It is valid for the
235 * result to be <code>null</code>.
236 *
237 * @return The outside border (possibly <code>null</code>).
238 */
239 public Border getOutsideBorder()
240 {
241 return outsideBorder;
242 }
243
244 /**
245 * Returns the inside border, which is painted between the bordered
246 * Component and the outside border. It is valid for the result to
247 * be <code>null</code>.
248 *
249 * @return The inside border (possibly <code>null</code>).
250 */
251 public Border getInsideBorder()
252 {
253 return insideBorder;
254 }
255 }