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 }