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: KDialog.java,v $ 023 Revision 1.12 2004/05/12 18:09:34 markl 024 javadoc updates 025 026 Revision 1.11 2004/05/05 23:19:38 markl 027 added setFont() method 028 029 Revision 1.10 2004/03/15 05:48:34 markl 030 moved accept/cancel logic from ComponentDialog to KDialog. 031 032 Revision 1.9 2003/01/19 09:41:00 markl 033 Javadoc & comment header updates. 034 035 Revision 1.8 2001/03/12 05:19:58 markl 036 Source code cleanup. 037 038 Revision 1.7 2000/12/18 23:37:29 markl 039 Added new constructors. 040 041 Revision 1.6 1999/07/19 04:09:52 markl 042 Fixed listener problem, renamed dispose() to destroy(). 043 044 Revision 1.5 1999/07/12 08:50:21 markl 045 Listen for texture change events. 046 047 Revision 1.4 1999/07/06 09:18:24 markl 048 Added cursor method. 049 050 Revision 1.3 1999/06/03 06:47:47 markl 051 Added startFocus() method. 052 053 Revision 1.2 1999/01/10 03:22:17 markl 054 added GPL header & RCS tag 055 ---------------------------------------------------------------------------- 056*/ 057 058package kiwi.ui.dialog; 059 060import java.awt.*; 061import java.awt.event.*; 062import java.beans.*; 063import java.util.*; 064import javax.swing.*; 065 066import kiwi.event.*; 067import kiwi.util.*; 068import kiwi.ui.*; 069 070/** <code>KDialog</code> is a trivial extension of <code>JDialog</code> 071 * that provides support for tiling the background of the dialog with an 072 * image and for firing dismissal events. 073 * <p> 074 * <code>KDialog</code> introduces the notion of a <i>cancelled</i> 075 * dialog versus an <i>accepted</i> dialog. Collectively, these are known as 076 * <i>dialog dismissals</i>. A dialog may be <i>cancelled</i> by 077 * pressing a <i>Cancel</i> button or by closing the dialog window 078 * altogether. A dialog may be <i>accepted</i> by pressing an <i>OK</i> button 079 * or entering a value in one of the dialog's input components. It is 080 * ultimately up to the subclasser to determine what constitutes a dialog 081 * dismissal. The convenience method <code>fireDialogDismissed()</code> is 082 * provided to generate dialog dismissal events. See 083 * <code>ComponentDialog</code> for an example of this functionality. 084 * 085 * <p><center> 086 * <img src="snapshot/KDialog.gif"><br> 087 * <i>An example KDialog.</i> 088 * </center> 089 * 090 * @see kiwi.ui.KPanel 091 * @see kiwi.ui.KFrame 092 * @see kiwi.ui.dialog.ComponentDialog 093 * @see kiwi.event.DialogDismissEvent 094 * 095 * @author Mark Lindner 096 */ 097 098public class KDialog extends JDialog 099 { 100 private KPanel _main; 101 private _PropertyChangeListener propListener; 102 private Vector _listeners = new Vector(); 103 private boolean cancelled = false; 104 105 /** Construct a new <code>KDialog</code>. 106 * 107 * @param parent The parent dialog for this dialog. 108 * @param title The title for this dialog. 109 * @param modal A flag specifying whether this dialog should be modal. 110 */ 111 112 public KDialog(Dialog parent, String title, boolean modal) 113 { 114 super(parent, title, modal); 115 116 _init(); 117 } 118 119 /** Construct a new <code>KDialog</code>. 120 * 121 * @param parent The parent frame for this dialog. 122 * @param title The title for this dialog. 123 * @param modal A flag specifying whether this dialog should be modal. 124 */ 125 126 public KDialog(Frame parent, String title, boolean modal) 127 { 128 super(parent, title, modal); 129 130 _init(); 131 } 132 133 /* 134 * Common initialization. 135 */ 136 137 private void _init() 138 { 139 getContentPane().setLayout(new GridLayout(1, 0)); 140 _main = new KPanel(UIChangeManager.getDefaultTexture()); 141 _main.setOpaque(true); 142 getContentPane().add(_main); 143 144 UIChangeManager.getInstance().registerComponent(getRootPane()); 145 propListener = new _PropertyChangeListener(); 146 UIChangeManager.getInstance().addPropertyChangeListener(propListener); 147 148 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 149 150 addWindowListener(new WindowAdapter() 151 { 152 public void windowClosing(WindowEvent evt) 153 { 154 if(canCancel()) 155 doCancel(); 156 else 157 doAccept(); 158 } 159 }); 160 } 161 162 /** Get a reference to the main container (in this case, the 163 * <code>KPanel</code> that is the child of the frame's content pane). 164 */ 165 166 protected KPanel getMainContainer() 167 { 168 return(_main); 169 } 170 171 /** Set the background image for the dialog. 172 * 173 * @param image The new background image. 174 */ 175 176 public void setTexture(Image image) 177 { 178 _main.setTexture(image); 179 invalidate(); 180 validate(); 181 repaint(); 182 } 183 184 /** Add a <code>DialogDismissListener</code> to this dialog's list of 185 * listeners. 186 * 187 * @param listener The listener to add. 188 * @see #removeDialogDismissListener 189 */ 190 191 public void addDialogDismissListener(DialogDismissListener listener) 192 { 193 _listeners.addElement(listener); 194 } 195 196 /** Remove a <code>DialogDismissListener</code> from this dialog's list 197 * of listeners. 198 * 199 * @param listener The listener to remove. 200 * @see #addDialogDismissListener 201 */ 202 203 public void removeDialogDismissListener(DialogDismissListener listener) 204 { 205 _listeners.removeElement(listener); 206 } 207 208 /** Fire a <i>dialog dismissed</i> event. Notifies listeners that this dialog 209 * is being dismissed. 210 * 211 * @param type The event type. 212 */ 213 214 protected void fireDialogDismissed(int type) 215 { 216 fireDialogDismissed(type, null); 217 } 218 219 /** Fire a <i>dialog dismissed</i> event. Notifies listeners that this dialog 220 * is being dismissed. 221 * 222 * @param type The event type. 223 * @param userObj An arbitrary user object argument to pass in the event. 224 */ 225 226 protected void fireDialogDismissed(int type, Object userObj) 227 { 228 DialogDismissEvent evt = null; 229 DialogDismissListener listener; 230 231 Enumeration e = _listeners.elements(); 232 while(e.hasMoreElements()) 233 { 234 listener = (DialogDismissListener)e.nextElement(); 235 if(evt == null) evt = new DialogDismissEvent(this, type, userObj); 236 listener.dialogDismissed(evt); 237 } 238 } 239 240 /** Show or hide the dialog. 241 * 242 * @param flag A flag specifying whether the dialog should be shown 243 * or hidden. If <code>true</code>, the <code>startFocus()</code> 244 * method is called to allow the subclasser to request focus for a 245 * given child component. 246 * 247 * @see #startFocus 248 */ 249 250 public void setVisible(boolean flag) 251 { 252 if(flag) 253 startFocus(); 254 255 super.setVisible(flag); 256 } 257 258 /** This method is called when the dialog is made visible; it should 259 * transfer focus to the appropriate child component. The default 260 * implementation does nothing. 261 */ 262 263 protected void startFocus() 264 { 265 } 266 267 /** Turn the busy cursor on or off for this dialog. 268 * 269 * @param flag If <code>true</code>, the wait cursor will be set for 270 * this dialog, otherwise the default cursor will be set. 271 */ 272 273 public void setBusyCursor(boolean flag) 274 { 275 setCursor(Cursor.getPredefinedCursor(flag ? Cursor.WAIT_CURSOR 276 : Cursor.DEFAULT_CURSOR)); 277 } 278 279 /** Determine if this dialog can be closed. 280 * 281 * @return <code>true</code> if the dialog may be closed, and 282 * <code>false</code> otherwise. The default implementation returns 283 * <code>true</code>. 284 */ 285 286 protected boolean canClose() 287 { 288 return(true); 289 } 290 291 /** Destroy this dialog. Call this method when the dialog is no longer 292 * needed. The dialog will detach its listeners from the 293 * <code>UIChanageManager</code>. 294 */ 295 296 public void destroy() 297 { 298 UIChangeManager.getInstance().unregisterComponent(getRootPane()); 299 UIChangeManager.getInstance().removePropertyChangeListener(propListener); 300 } 301 302 /** Accept user input. The dialog calls this method in response to a 303 * click on the dialog's <i>OK</i> button. If this method returns 304 * <code>true</code>, the dialog disappears; otherwise, it remains 305 * on the screen. This method can be overridden to check input in 306 * the dialog before allowing it to be dismissed. The default 307 * implementation of this method returns <code>true</code>. 308 * 309 * @return <code>true</code> if the dialog may be dismissed, and 310 * <code>false</code> otherwise. 311 * 312 * @since Kiwi 2.0 313 */ 314 315 protected boolean accept() 316 { 317 return(true); 318 } 319 320 /** Programmatically accept user input. 321 * 322 * @since Kiwi 2.0 323 */ 324 325 protected void doAccept() 326 { 327 if(accept()) 328 { 329 setCancelled(false); 330 fireDialogDismissed(DialogDismissEvent.OK); 331 setVisible(false); 332 dispose(); 333 } 334 } 335 336 /** Cancel the dialog. The dialog calls this method in response to a click on 337 * the dialog's <i>Cancel</i> button, or on a close of the dialog window 338 * itself. Subclassers may override this method to provide any special 339 * processing that is required when the dialog is cancelled. The default 340 * implementation of this method does nothing. 341 * 342 * @since Kiwi 2.0 343 */ 344 345 protected void cancel() 346 { 347 } 348 349 /** Programmatically cancel the dialog. 350 * 351 * @since Kiwi 2.0 352 */ 353 354 protected void doCancel() 355 { 356 setCancelled(true); 357 cancel(); 358 setVisible(false); 359 dispose(); 360 fireDialogDismissed(DialogDismissEvent.CANCEL); 361 } 362 363 /** Get the <i>cancelled</i> state of the dialog. This method should be 364 * called after the dialog is dismissed to determine if it was cancelled by 365 * the user. 366 * 367 * @return <code>true</code> if the dialog was cancelled, and 368 * <code>false</code> otherwise. 369 * 370 * @since Kiwi 2.0 371 */ 372 373 public boolean isCancelled() 374 { 375 return(cancelled); 376 } 377 378 /** Set the <i>cancelled</i> state of the dialog. Custom dialogs which 379 * subclass <code>KDialog</code> directory may use this method to record the 380 * fact that the dialog was cancelled. 381 * 382 * @since Kiwi 2.0 383 */ 384 385 protected void setCancelled(boolean flag) 386 { 387 cancelled = flag; 388 } 389 390 /** Determine if the dialog can be cancelled. This method is called in 391 * response to a click on the <i>Cancel</i> button or on the dialog 392 * window's close icon/option. Subclassers may wish to override this 393 * method to prevent cancellation of a window in certain circumstances. 394 * 395 * @return The default implementation returns<code>true</code>. 396 */ 397 398 protected boolean canCancel() 399 { 400 return(true); 401 } 402 403 /* PropertyChangeListener */ 404 405 private class _PropertyChangeListener implements PropertyChangeListener 406 { 407 public void propertyChange(PropertyChangeEvent evt) 408 { 409 if(evt.getPropertyName().equals(UIChangeManager.TEXTURE_PROPERTY)) 410 setTexture((Image)evt.getNewValue()); 411 } 412 } 413 414 /** Set the font for this dialog window. This method sets the font for 415 * each component in the window's component hierarchy. 416 * 417 * @param font The new font. 418 * 419 * @since Kiwi 2.0 420 */ 421 422 public void setFont(Font font) 423 { 424 KiwiUtils.setFonts(getMainContainer(), font); 425 } 426 427 } 428 429/* end of source file */