001/* ---------------------------------------------------------------------------- 002 The Kiwi Toolkit - A Java Class Library 003 Copyright (C) 1998-2004 Mark A. Lindner 004 005 This library is free software; you can redistribute it and/or 006 modify it under the terms of the GNU General Public License as 007 published by the Free Software Foundation; either version 2 of the 008 License, or (at your option) any later version. 009 010 This library is distributed in the hope that it will be useful, 011 but WITHOUT ANY WARRANTY; without even the implied warranty of 012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 General Public License for more details. 014 015 You should have received a copy of the GNU General Public License 016 along with this library; if not, write to the Free Software 017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 018 02111-1307, USA. 019 020 The author may be contacted at: mark_a_lindner@yahoo.com 021 ---------------------------------------------------------------------------- 022 $Log: KPanel.java,v $ 023 Revision 1.8 2004/05/31 07:26:36 markl 024 rewrite of focus order methods 025 026 Revision 1.7 2004/05/12 19:02:38 markl 027 comment block updates 028 029 Revision 1.6 2003/01/19 09:50:53 markl 030 Javadoc & comment header updates. 031 032 Revision 1.5 2001/03/12 09:27:56 markl 033 Source code and Javadoc cleanup. 034 035 Revision 1.4 1999/04/26 09:27:15 markl 036 Added support for solid backgrounds. 037 038 Revision 1.3 1999/04/25 04:12:41 markl 039 Changes to support solid backgrounds in addition to textures. 040 041 Revision 1.2 1999/01/10 02:25:57 markl 042 added GPL header & RCS tag 043 ---------------------------------------------------------------------------- 044*/ 045 046package kiwi.ui; 047 048import java.awt.*; 049import javax.swing.*; 050 051/** An extension of <code>JPanel</code> that provides some additional 052 * functionality including support for background texture tiling and 053 * named-component lookup. Lightweight components nested within the 054 * <code>KPanel</code> should be transparent and unbuffered; the tiled 055 * background will not show through heavyweight components. 056 * <p> 057 * Note that images with transparent portions should <i>not</i> be used with 058 * <code>KPanel</code>s. 059 * <p> 060 * A <code>KPanel</code> will always be transparent if a background 061 * texture has not been specified. Therefore <code>KPanel</code>s may be 062 * safely nested if only the outermost instance has a texture applied. It is 063 * recommended that <code>KPanel</code>s always be used in place of Swing 064 * <code>JPanel</code>s. 065 * <p> 066 * In most cases it is convenient to use a <code>KFrame</code> to provide a 067 * textured background for an entire window. 068 * <p> 069 * If a solid color background is desired in place of a texture, then the 070 * outermost <code>KPanel</code> should be made opaque via the call 071 * <code>setOpaque(true)</code>, and the texture should be turned off via a 072 * call to <code>setTexture(null)</code>. The background color can be set 073 * using <code>setBackground()</code> as usual. 074 * 075 * @see kiwi.ui.KFrame 076 * 077 * @author Mark Lindner 078 */ 079 080public class KPanel extends JPanel 081 { 082 private Image image = null; 083 084 /** Construct a new <code>KPanel</code>. The newly created 085 * <code>KPanel</code> will be transparent. 086 */ 087 088 public KPanel() 089 { 090 super(false); 091 super.setOpaque(false); 092 } 093 094 /** Construct a new <code>KPanel</code>. Creates a new 095 * <code>KPanel</code> with the specified layout manager. The newly 096 * created <code>KPanel</code> will be transparent. 097 * 098 * @param lm The layout manager to use for the panel. 099 */ 100 101 public KPanel(LayoutManager lm) 102 { 103 super(lm, false); 104 super.setOpaque(false); 105 } 106 107 /** Construct a new <code>KPanel</code>. Creates a new 108 * <code>KPanel</code> with the specified layout manager and 109 * background image. 110 * 111 * @param lm The layout manager to use for the panel. 112 * @param image The image with which the background of the panel will be 113 * tiled. 114 */ 115 116 public KPanel(LayoutManager lm, Image image) 117 { 118 super(lm, false); 119 120 this.image = image; 121 super.setOpaque(false); 122 } 123 124 /** Construct a new <code>KPanel</code>. Creates a new 125 * <code>KPanel</code> with a <code>BorderLayout</code> and the 126 * specified background image. 127 * 128 * @param image The image with which the background of the panel will be 129 * tiled. 130 */ 131 132 public KPanel(Image image) 133 { 134 super(new BorderLayout(0, 0), true); 135 136 this.image = image; 137 super.setOpaque(false); 138 } 139 140 /** Paint the component. Tiles the component with the background image, 141 * if one has been provided. 142 */ 143 144 public void paintComponent(Graphics gc) 145 { 146 if(image == null) 147 { 148 super.paintComponent(gc); 149 } 150 else 151 { 152 Dimension size = new Dimension(); 153 getSize(size); 154 int ih = image.getHeight(null); 155 int iw = image.getWidth(null); 156 157 int vc = (size.height / ih) + 1; 158 int hc = (size.width / iw) + 1; 159 160 for(int y = 0; y < vc; y++) 161 for(int x = 0; x < hc; x++) 162 gc.drawImage(image, x * iw, y * ih, null); 163 } 164 } 165 166 /** Set the background texture. 167 * 168 * @param image The image to use as the background texture for the panel. 169 */ 170 171 public void setTexture(Image image) 172 { 173 this.image = image; 174 repaint(); 175 } 176 177 /** Search for a component by name. Components can be named using the 178 * <code>setName()</code> method of <code>Component</code>. This is a useful 179 * way of identifying a component when comparison by reference is not 180 * possible. This method searches this <code>KPanel</code>'s component 181 * hierarchy for a component with the given name. 182 * 183 * @param name The name of the component to search for. 184 * @return The matching component, or <code>null</code> if there is no 185 * component in the component hierarchy with the given name. 186 * @see java.awt.Component#setName 187 * @see java.awt.Component#getName 188 */ 189 190 public Component getComponentByName(String name) 191 { 192 return(findComponent(this, name)); 193 } 194 195 /* 196 */ 197 198 private Component findComponent(Container cont, String name) 199 { 200 int ct = cont.getComponentCount(); 201 202 for(int i = 0; i < ct; i++) 203 { 204 Component subc = cont.getComponent(i); 205 if(subc.getName().equals(name)) 206 return(subc); 207 } 208 209 // none of them matched, so recurse 210 211 for(int i = 0; i < ct; i++) 212 { 213 Component c = cont.getComponent(i); 214 215 if(c instanceof Container) 216 { 217 Component subc = findComponent((Container)c, name); 218 if(subc != null) 219 return(subc); 220 } 221 } 222 223 return(null); 224 } 225 226 /** Set the focus order for this component. The focus order specifies the 227 * order in which child components will receive focus when the user presses 228 * the tab key to move between input components. 229 * 230 * @param order The component array representing the desired focus order. 231 */ 232 233 public void setFocusOrder(JComponent order[]) 234 { 235 setFocusCycleRoot(true); 236 setFocusTraversalPolicy(new KFocusTraversalPolicy(order)); 237 } 238 239 /* 240 */ 241 242 private class KFocusTraversalPolicy extends FocusTraversalPolicy 243 { 244 private JComponent order[]; 245 246 /* 247 */ 248 249 KFocusTraversalPolicy(JComponent order[]) 250 { 251 this.order = order; 252 } 253 254 /* 255 */ 256 257 public Component getComponentAfter(Container focusCycleRoot, 258 Component component) 259 { 260 int i = 0; 261 262 for(; i < order.length; i++) 263 { 264 if((Component)order[i] == component) 265 break; 266 } 267 268 if(i >= order.length - 1) 269 return(null); 270 else 271 return((Component)order[++i]); 272 } 273 274 /* 275 */ 276 277 public Component getComponentBefore(Container focusCycleRoot, 278 Component component) 279 { 280 int i = 0; 281 282 for(; i < order.length; i++) 283 { 284 if((Component)order[i] == component) 285 break; 286 } 287 288 if((i >= order.length - 1) || (i == 0)) 289 return(null); 290 else 291 return((Component)order[--i]); 292 } 293 294 /* 295 */ 296 297 public Component getFirstComponent(Container focusCycleRoot) 298 { 299 if(order.length == 0) 300 return(null); 301 else 302 return((Component)order[0]); 303 } 304 305 /* 306 */ 307 308 public Component getLastComponent(Container focusCycleRoot) 309 { 310 if(order.length == 0) 311 return(null); 312 else 313 return((Component)order[order.length - 1]); 314 } 315 316 /* 317 */ 318 319 public Component getDefaultComponent(Container focusCycleRoot) 320 { 321 return(getFirstComponent(focusCycleRoot)); 322 } 323 } 324 325 } 326 327/* end of source file */