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: ButtonPanel.java,v $ 023 Revision 1.13 2004/05/12 19:08:19 markl 024 comment block updates 025 026 Revision 1.12 2003/01/19 09:50:52 markl 027 Javadoc & comment header updates. 028 029 Revision 1.11 2001/03/12 09:27:52 markl 030 Source code and Javadoc cleanup. 031 032 Revision 1.10 2000/10/11 10:45:47 markl 033 Fixes to support AbstractButtons. 034 035 Revision 1.9 1999/11/19 06:23:41 markl 036 Added getButton() method. 037 038 Revision 1.8 1999/08/04 08:09:27 markl 039 Rewrote to use a custom layout manager. 040 041 Revision 1.7 1999/07/30 03:59:18 markl 042 Bug fix. 043 044 Revision 1.6 1999/07/29 04:34:33 markl 045 Added some more sophisticated layout logic. 046 047 Revision 1.5 1999/02/28 00:27:05 markl 048 Minor fixes. 049 050 Revision 1.4 1999/02/27 12:08:17 markl 051 Minor fixes. 052 053 Revision 1.3 1999/02/27 12:06:07 markl 054 Added alignment parameter. 055 056 Revision 1.2 1999/01/10 01:00:58 markl 057 added GPL header & RCS tag 058 ---------------------------------------------------------------------------- 059*/ 060 061package kiwi.ui; 062 063import java.awt.*; 064import javax.swing.*; 065 066/** This class is a simple extension of <code>KPanel</code> that arranges 067 * buttons in a row, in such a way that the buttons are all of equal size, 068 * and justified flush with the right or left edge of the panel. Many Kiwi 069 * dialogs and frames provide buttons in their lower-right areas or toolbars 070 * in their upper-left areas that are positioned in just this way; this 071 * class eliminates the need to perform the layout explicitly in code each 072 * time this effect is desired. 073 * <p> 074 * The row of buttons is anchored at either the left or the right edge of 075 * the panel. If the sum of the preferred widths of the buttons exceeds the 076 * available horizontal space, the buttons are compressed horizontally to 077 * fit. 078 * 079 * @see kiwi.ui.KPanel 080 * 081 * @author Mark Lindner 082 */ 083 084public class ButtonPanel extends KPanel 085 { 086 private static final int LEFT = 0, RIGHT = 1; 087 private KPanel p_buttons; 088 /** The default horizontal spacing. */ 089 public static final int DEFAULT_SPACING = 5; 090 091 /** Construct a new <code>ButtonPanel</code> with the default horizontal 092 * spacing and right alignment. 093 */ 094 095 public ButtonPanel() 096 { 097 this(SwingConstants.RIGHT, DEFAULT_SPACING); 098 } 099 100 /** Construct a new <code>ButtonPanel</code> with default horizontal 101 * spacing and the given alignment. 102 * 103 * @param alignment The alignment of the buttons within their containing 104 * panel; one of <code>SwingConstants.LEFT</code> or 105 * <code>SwingConstants.RIGHT</code>. 106 */ 107 108 public ButtonPanel(int alignment) 109 { 110 this(alignment, DEFAULT_SPACING); 111 } 112 113 /** Construct a new <code>ButtonPanel</code> with the given horizontal 114 * spacing and alignment. 115 * 116 * @param spacing The size of the gap (in pixels) to place between buttons 117 * horizontally. 118 * @param alignment The alignment of the buttons within their containing 119 * panel; one of <code>SwingConstants.LEFT</code> or 120 * <code>SwingConstants.RIGHT</code>. 121 */ 122 123 public ButtonPanel(int alignment, int spacing) 124 { 125 setOpaque(false); 126 127 int anchor = ((alignment == SwingConstants.RIGHT) ? RIGHT : LEFT); 128 setLayout(new AnchorLayout(anchor)); 129 130 p_buttons = new KPanel(); 131 p_buttons.setLayout(new GridLayout(1, 0, spacing, 0)); 132 133 add(p_buttons); 134 } 135 136 /** Add a button to the <code>ButtonPanel</code>. 137 * 138 * @param button The button to add. 139 * @see #removeButton 140 */ 141 142 public void addButton(AbstractButton button) 143 { 144 p_buttons.add(button); 145 } 146 147 /** Add a button to the <code>ButtonPanel</code> at the specified position. 148 * 149 * @param button The button to add. 150 * @param pos The position at which to add the button. The value 0 denotes 151 * the first position, and -1 denotes the last position. 152 * @exception java.lang.IllegalArgumentException If the value of 153 * <code>pos</code> is invalid. 154 */ 155 156 public void addButton(AbstractButton button, int pos) 157 throws IllegalArgumentException 158 { 159 p_buttons.add(button, pos); 160 } 161 162 /** Get a reference to the button at the specified position in the 163 * <code>ButtonPanel</code>. 164 * 165 * @param pos The position of the button to retrieve. 166 * @return The button. 167 */ 168 169 public AbstractButton getButton(int pos) 170 { 171 return((AbstractButton)p_buttons.getComponent(pos)); 172 } 173 174 /** Remove a button from the <code>ButtonPanel</code>. 175 * 176 * @param button The button to remove. 177 * @see #addButton 178 */ 179 180 public void removeButton(AbstractButton button) 181 { 182 p_buttons.remove(button); 183 } 184 185 /** Remove a button from the specified position in the 186 * <code>ButtonPanel</code>. 187 * 188 * @param pos The position of the button to remove, where 0 denotes the 189 * first position. 190 */ 191 192 public void removeButton(int pos) 193 { 194 p_buttons.remove(pos); 195 } 196 197 /** Get the number of buttons in this <code>ButtonPanel</code>. 198 * 199 * @return The number of buttons. 200 */ 201 202 public int getButtonCount() 203 { 204 return(p_buttons.getComponentCount()); 205 } 206 207 /* The custom layout manager for this component. Normally I would frown upon 208 * writing a layout manager, but in this case, none of the existing layout 209 * managers did the job, and there was no other elegant and foolproof way to 210 * achieve this effect. 211 * 212 * This layout manager can only handle one child component in a container. 213 * It anchors the child either to the right or the left edge of its parent. 214 * The child's size is set to its preferred size, if the parent is big 215 * enough. Otherwise, the child's size is set to the size of the parent. 216 */ 217 218 private class AnchorLayout implements LayoutManager2 219 { 220 private int anchor; 221 private Component c = null; 222 private Dimension noSize = new Dimension(0, 0); 223 224 public AnchorLayout(int anchor) 225 { 226 this.anchor = anchor; 227 } 228 229 public float getLayoutAlignmentX(Container cont) 230 { 231 return(0.5f); 232 } 233 234 public float getLayoutAlignmentY(Container cont) 235 { 236 return(0.5f); 237 } 238 239 public void addLayoutComponent(String name, Component comp) 240 { 241 if(c != null) 242 return; 243 244 c = comp; 245 } 246 247 public void addLayoutComponent(Component comp, Object constraints) 248 { 249 addLayoutComponent((String)null, comp); 250 } 251 252 public void removeLayoutComponent(Component comp) 253 { 254 if(comp == c) 255 c = null; 256 } 257 258 private Dimension layoutSize(Dimension size, Insets insets) 259 { 260 if(c == null) 261 return(noSize); 262 263 return(new Dimension((insets.left + size.width + insets.right), 264 (insets.top + size.height + insets.bottom))); 265 } 266 267 public Dimension maximumLayoutSize(Container cont) 268 { 269 return(c.getMaximumSize()); 270 } 271 272 public void invalidateLayout(Container cont) 273 { 274 // nothing to do 275 } 276 277 // The minimum layout size is based on the component's minimum size. 278 279 public Dimension minimumLayoutSize(Container cont) 280 { 281 return(layoutSize(c.getMinimumSize(), cont.getInsets())); 282 } 283 284 // The preferred layout size is based on the component's preferred size. 285 286 public Dimension preferredLayoutSize(Container cont) 287 { 288 return(layoutSize(c.getPreferredSize(), cont.getInsets())); 289 } 290 291 // Lay out the container. 292 293 public void layoutContainer(Container cont) 294 { 295 if(c == null) 296 return; 297 298 Dimension size = cont.getSize(); 299 Insets insets = cont.getInsets(); 300 301 int w = size.width - (insets.left + insets.right); 302 int h = size.height - (insets.top + insets.bottom); 303 Dimension p = c.getPreferredSize(); 304 305 int cw = p.width; 306 307 if(cw > w) 308 { 309 cw = w; 310 c.setSize(cw, h); 311 } 312 else 313 c.setSize(p); 314 315 int offset = ((anchor == LEFT) ? 0 : (w - cw)); 316 317 c.setLocation(insets.left + offset, insets.top); 318 } 319 } 320 321 } 322 323/* end of source file */