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: ComponentDialog.java,v $ 023 Revision 1.16 2004/05/31 07:45:25 markl 024 added installDialogUI(), new form of setComment() 025 026 Revision 1.15 2004/03/16 06:43:39 markl 027 LocaleManager method change 028 029 Revision 1.14 2004/03/15 05:48:34 markl 030 moved accept/cancel logic from ComponentDialog to KDialog. 031 032 Revision 1.13 2004/01/23 00:06:06 markl 033 javadoc corrections 034 035 Revision 1.12 2003/04/30 04:35:02 markl 036 removed unnecessary pack() call. 037 038 Revision 1.11 2003/01/19 09:40:41 markl 039 Added doAccept() and doCancel() methods. 040 041 Revision 1.10 2001/03/20 00:54:54 markl 042 Fixed deprecated calls. 043 044 Revision 1.9 2001/03/12 09:56:55 markl 045 KLabel/KLabelArea changes. 046 047 Revision 1.8 2001/03/12 05:19:57 markl 048 Source code cleanup. 049 050 Revision 1.7 2000/12/18 23:37:29 markl 051 Added new constructors. 052 053 Revision 1.6 2000/10/11 10:44:26 markl 054 Fixed close window logic. 055 056 Revision 1.5 1999/06/03 06:47:15 markl 057 Added canCancel() method. 058 059 Revision 1.4 1999/04/19 06:00:12 markl 060 I18N changes. 061 062 Revision 1.3 1999/02/07 08:09:16 markl 063 made setComment() public 064 065 Revision 1.2 1999/01/10 03:22:17 markl 066 added GPL header & RCS tag 067 ---------------------------------------------------------------------------- 068*/ 069 070package kiwi.ui.dialog; 071 072import java.awt.*; 073import java.awt.event.*; 074import javax.swing.*; 075import javax.swing.text.JTextComponent; 076import javax.swing.border.EmptyBorder; 077 078import kiwi.ui.*; 079import kiwi.util.*; 080import kiwi.event.*; 081 082/** A base class for custom dialog windows. This class provides some base 083 * functionality that can be useful across many different types of dialogs. 084 * The class constructs a skeleton dialog consisting of an optional comment 085 * line, an icon, <i>OK</i> and <i>Cancel</i> buttons, and a middle area that 086 * must be filled in by subclassers. 087 * <p> 088 * A <code>ComponentDialog</code> is <i>accepted</i> by clicking the 089 * <i>OK</i> button, though subclassers can determine the conditions under 090 * which a dialog may be accepted by overriding the <code>accept()</code> 091 * method; it is <i>cancelled</i> by clicking the <i>Cancel</i> button or 092 * closing the window. 093 * 094 * @author Mark Lindner 095 */ 096 097public abstract class ComponentDialog extends KDialog 098 { 099 /** The OK button. */ 100 protected KButton b_ok; 101 102 /** The Cancel button. */ 103 protected KButton b_cancel = null; 104 105 private _ActionListener actionListener; 106 private KPanel main; 107 private KLabel iconLabel, commentLabel; 108 private JTextField inputComponent = null; 109 private ButtonPanel buttons; 110 private int fixedButtons = 1; 111 112 /** Construct a new <code>ComponentDialog</code>. 113 * 114 * @param parent The parent dialog for this dialog. 115 * @param title The title for this dialog's window. 116 * @param modal A flag specifying whether this dialog will be modal. 117 */ 118 119 public ComponentDialog(Dialog parent, String title, boolean modal) 120 { 121 this(parent, title, modal, true); 122 } 123 124 /** Construct a new <code>ComponentDialog</code>. 125 * 126 * @param parent The parent dialog for this dialog. 127 * @param title The title for this dialog's window. 128 * @param modal A flag specifying whether this dialog will be modal. 129 * @param hasCancel A flag specifying whether this dialog should have a 130 * <i>Cancel</i> button. 131 */ 132 133 public ComponentDialog(Dialog parent, String title, boolean modal, 134 boolean hasCancel) 135 { 136 super(parent, title, modal); 137 138 _init(hasCancel); 139 } 140 141 /** Construct a new <code>ComponentDialog</code>. 142 * 143 * @param parent The parent frame for this dialog. 144 * @param title The title for this dialog's window. 145 * @param modal A flag specifying whether this dialog will be modal. 146 */ 147 148 public ComponentDialog(Frame parent, String title, boolean modal) 149 { 150 this(parent, title, modal, true); 151 } 152 153 /** Construct a new <code>ComponentDialog</code>. 154 * 155 * @param parent The parent frame for this dialog. 156 * @param title The title for this dialog's window. 157 * @param modal A flag specifying whether this dialog will be modal. 158 * @param hasCancel A flag specifying whether this dialog should have a 159 * <i>Cancel</i> button. 160 */ 161 162 public ComponentDialog(Frame parent, String title, boolean modal, 163 boolean hasCancel) 164 { 165 super(parent, title, modal); 166 167 _init(hasCancel); 168 } 169 170 /* 171 * Common initialization. 172 */ 173 174 private void _init(boolean hasCancel) 175 { 176 LocaleData loc = LocaleManager.getDefault().getLocaleData("KiwiDialogs"); 177 178 actionListener = new _ActionListener(); 179 180 main = getMainContainer(); 181 main.setBorder(new EmptyBorder(5, 5, 5, 5)); 182 main.setLayout(new BorderLayout(5, 5)); 183 184 commentLabel = new KLabel(loc.getMessage("kiwi.dialog.prompt")); 185 main.add("North", commentLabel); 186 187 iconLabel = new KLabel(); 188 iconLabel.setBorder(new EmptyBorder(5, 0, 5, 0)); 189 iconLabel.setVerticalAlignment(SwingConstants.CENTER); 190 iconLabel.setHorizontalAlignment(SwingConstants.CENTER); 191 192 buttons = new ButtonPanel(); 193 194 b_ok = new KButton(loc.getMessage("kiwi.button.ok")); 195 b_ok.addActionListener(actionListener); 196 buttons.addButton(b_ok); 197 198 if(hasCancel) 199 { 200 b_cancel = new KButton(loc.getMessage("kiwi.button.cancel")); 201 b_cancel.addActionListener(actionListener); 202 buttons.addButton(b_cancel); 203 fixedButtons++; 204 } 205 206 main.add("South", buttons); 207 208 installDialogUI(); 209 } 210 211 /** Install the component returned by <code>buildDialogUI()</code> 212 * into the dialog. If it is not possible to build the dialog UI at 213 * the time that the constructor calls <code>buildDialogUI()</code>, 214 * that method should return <b>null</b>. The subclass constructor 215 * can then explicitly call <code>installDialogUI()</code>, at which 216 * time <code>buildDialogUI</code> should return a valid component. 217 */ 218 219 protected void installDialogUI() 220 { 221 Component c = buildDialogUI(); 222 if(c != null) 223 { 224 main.add("Center", c); 225 pack(); 226 } 227 } 228 229 /** Construct the component that will be displayed in the center of the 230 * dialog window. Subclassers implement this method to customize the look of 231 * the dialog. 232 * 233 * @return A <code>Component</code> to display in the dialog, or 234 * <code>null</code> if the component will be constructed later. 235 */ 236 237 protected abstract Component buildDialogUI(); 238 239 /** Show or hide the dialog. 240 */ 241 242 public void setVisible(boolean flag) 243 { 244 if(flag) 245 { 246 validate(); 247 //pack(); 248 } 249 super.setVisible(flag); 250 } 251 252 /** Register a text field with this dialog. In some dialogs, most notably 253 * <code>KInputDialog</code>, pressing <i>Return</i> in a text field is 254 * equivalent to pressing the dialog's <i>OK</i> button. Subclassers may use 255 * this method to register a text field that should function in this way. 256 * 257 * @param c The <code>JTextField</code> to register. 258 */ 259 260 protected void registerTextInputComponent(JTextField c) 261 { 262 inputComponent = c; 263 264 inputComponent.addActionListener(actionListener); 265 } 266 267 /** This is overridden to fix a Swing layout bug. */ 268 269 /* 270 public void pack() 271 { 272 // only do this for JDK 1.3 and earlier 273 274 // add a test here 275 276 boolean old = isResizable(); 277 setResizable(true); 278 super.pack(); 279 setResizable(old); 280 } 281 */ 282 283 /** Change the dialog's comment. 284 * 285 * @param comment The new text to display in the comment portion of the 286 * dialog. 287 */ 288 289 public void setComment(String comment) 290 { 291 setComment(null, comment); 292 } 293 294 /** Change the dialog's comment. 295 * 296 * @param comment The new text to display in the comment portion of the 297 * dialog. 298 * @param icon An icon to display to the left of the comment text. 299 * 300 * @since Kiwi 2.0 301 */ 302 303 public void setComment(Icon icon, String comment) 304 { 305 commentLabel.setText(comment); 306 commentLabel.setIcon(icon); 307 commentLabel.invalidate(); 308 commentLabel.validate(); 309 } 310 311 /** Set the icon to display in the left part of the dialog 312 * window. The method can be called by classes that extend this 313 * class to provide an appropriate icon for the dialog. 314 * 315 * @param icon The icon. 316 */ 317 318 public void setIcon(Icon icon) 319 { 320 if(icon != null) 321 { 322 iconLabel.setIcon(icon); 323 main.add("West", iconLabel); 324 } 325 else 326 main.remove(iconLabel); 327 } 328 329 /* action listener */ 330 331 private class _ActionListener implements ActionListener 332 { 333 public void actionPerformed(ActionEvent evt) 334 { 335 Object o = evt.getSource(); 336 337 if((o == b_ok) || (o == inputComponent)) 338 { 339 doAccept(); 340 } 341 else if(o == b_cancel) 342 { 343 if(canCancel()) 344 doCancel(); 345 } 346 } 347 } 348 349 /** Determine if the dialog can be cancelled. This method is called in 350 * response to a click on the <i>Cancel</i> button or on the dialog 351 * window's close icon/option. Subclassers may wish to override this 352 * method to prevent cancellation of a window in certain circumstances. 353 * 354 * @return <code>true</code> if the dialog may be cancelled, 355 * <code>false</code> otherwise. The default implementation returns 356 * <code>true</code> if the dialog has a <i>Cancel</i> button and 357 * <code>false</code> otherwise. 358 */ 359 360 protected boolean canCancel() 361 { 362 return(b_cancel != null); 363 } 364 365 /* Set the opacity on all the buttons */ 366 367 void setButtonOpacity(boolean flag) 368 { 369 Component c[] = buttons.getComponents(); 370 371 for(int i = 0; i < c.length; i++) 372 { 373 if(c[i] instanceof JButton) 374 ((JButton)c[i]).setOpaque(flag); 375 } 376 } 377 378 /** Add a button to the dialog's button panel. The button is added 379 * immediately before the <i>OK</i> button. 380 * 381 * @param button The button to add. 382 */ 383 384 protected void addButton(JButton button) 385 { 386 addButton(button, -1); 387 } 388 389 /** Add a button to the dialog's button panel at the specified position. 390 * 391 * @param button The button to add. 392 * @param pos The position at which to add the button. A value of 0 denotes 393 * the first position, and -1 denotes the last position. The possible 394 * range of values for <code>pos</code> excludes the <i>OK</i> and 395 * (if present) <i>Cancel</i> buttons; buttons may not be added after 396 * these "fixed" buttons. 397 */ 398 399 protected void addButton(JButton button, int pos) 400 throws IllegalArgumentException 401 { 402 int bc = buttons.getButtonCount(); 403 int maxpos = bc - fixedButtons; 404 405 if(pos > maxpos) 406 throw(new IllegalArgumentException("Position out of range.")); 407 else if(pos < 0) 408 pos = maxpos; 409 410 buttons.addButton(button, pos); 411 } 412 413 /** Remove a button from the dialog's button panel. 414 * 415 * @param button The button to remove. Neither the <i>OK</i> nor the 416 * <i>Cancel</i> button may be removed. 417 */ 418 419 protected void removeButton(JButton button) 420 { 421 if((button != b_ok) && (button != b_cancel)) 422 buttons.removeButton(button); 423 } 424 425 /** Remove a button from the specified position in the dialog's button 426 * panel. 427 * 428 * @param pos The position of the button to remove, where 0 denotes 429 * the first position, and -1 denotes the last position. The possible 430 * range of values for <code>pos</code> excludes the <i>OK</i> and 431 * (if present) <i>Cancel</i> buttons; these "fixed" buttons may not be 432 * removed. 433 */ 434 435 protected void removeButton(int pos) 436 { 437 int bc = buttons.getButtonCount(); 438 int maxpos = bc - fixedButtons; 439 440 if(pos > maxpos) 441 throw(new IllegalArgumentException("Position out of range.")); 442 else if(pos < 0) 443 pos = maxpos; 444 445 buttons.removeButton(pos); 446 } 447 448 /** Set the label text for the <i>OK</i> button. 449 * 450 * @param text The text for the accept button (for example, "Yes"). 451 */ 452 453 public void setAcceptButtonText(String text) 454 { 455 b_ok.setText(text); 456 } 457 458 /** Set the label text for the <i>Cancel</i> button. 459 * 460 * @param text The text for the cancel button (for example, "No"). 461 */ 462 463 public void setCancelButtonText(String text) 464 { 465 if(b_cancel != null) 466 b_cancel.setText(text); 467 } 468 469 } 470 471/* end of source file */