001 package sale; 002 003 import javax.swing.*; 004 import javax.swing.event.*; 005 006 import java.awt.event.*; 007 import java.awt.BorderLayout; 008 import java.io.*; 009 010 import sale.stdforms.*; 011 import sale.events.*; 012 013 /** 014 * A JDialog that can display Form- and MenuSheets. 015 * 016 * <p>You can use this frame to pop up messages and dialogs in extra windows, while 017 * maintaining consistency with the rest of the GUI by using the familiar FormSheet 018 * look'n'feel.</p> 019 * 020 * <p>The frame will display one {@link FormSheet}, and, by default, will close when the FormSheet 021 * is closed. Closing the frame using the systems menu or any other OS dependent gesture 022 * will result in a call to {@link FormSheet#cancel()} on the FormSheet.</p> 023 * 024 * <p>Also, the frame may display a {@link MenuSheet}. It can therefore be used wherever a Display 025 * can be used.</p> 026 * 027 * <p><strong>Attention:</strong> This class is not meant to be serialized.</p> 028 * 029 * @author Steffen Zschaler 030 * @version 2.0 25/05/1999 031 * @since v2.0 032 */ 033 public class JDisplayDialog extends JDialog implements Display, FormSheetContainer { 034 035 /** 036 * ID for serialization. 037 */ 038 private static final long serialVersionUID = -326751707151867738L; 039 040 /** 041 * Object used to block {@link #setFormSheet} when the FormSheet demands it. 042 */ 043 private transient Object m_oWaiter; 044 /** 045 * Return the object used to block {@link #setFormSheet} when the FormSheet demands it. 046 */ 047 private Object getWaiter() { 048 if (m_oWaiter == null) { 049 m_oWaiter = new Object(); 050 } 051 052 return m_oWaiter; 053 } 054 055 /** 056 * The currently displaying component. 057 */ 058 private transient JComponent m_jcmpComponent; 059 060 /** 061 * The currently displaying button bar panel. 062 */ 063 private transient JPanel m_jpButtonBar; 064 065 /** 066 * The current FormSheet. 067 */ 068 private transient FormSheet m_fsCurrent; 069 070 /** 071 * The current MenuSheet. 072 */ 073 private transient MenuSheet m_msCurrent; 074 075 /** 076 * The list of listeners. 077 */ 078 protected transient EventListenerList m_ellListeners = new EventListenerList(); 079 080 /** 081 * JDisplayDialogs are not meant to be serialized! 082 */ 083 private void writeObject(ObjectOutputStream oos) throws IOException { 084 throw new NotSerializableException("JDisplayDialog"); 085 } 086 087 /** 088 * Create a new JDisplayDialog. 089 */ 090 public JDisplayDialog() { 091 super(); 092 093 getContentPane().setLayout(new java.awt.BorderLayout()); 094 095 addWindowListener(new WindowAdapter() { 096 public void windowClosing(WindowEvent e) { 097 if (m_fsCurrent != null) { 098 m_fsCurrent.cancel(); 099 } 100 } 101 }); 102 } 103 104 /** 105 * Create a new JDisplayDialog with the given owner. 106 * 107 * @param jfOwner the JFrame owning the display dialog. 108 */ 109 public JDisplayDialog(JFrame jfOwner) { 110 super(jfOwner); 111 112 getContentPane().setLayout(new java.awt.BorderLayout()); 113 114 addWindowListener(new WindowAdapter() { 115 public void windowClosing(WindowEvent e) { 116 if (m_fsCurrent != null) { 117 m_fsCurrent.cancel(); 118 } 119 } 120 }); 121 } 122 123 // FormSheetContainer interface methods. 124 125 /** 126 * Close a FormSheet. 127 * 128 * <p>If a FormSheet is closed, by default, the JDisplayDialog containing it is also closed. You can, 129 * however, alter this behavior by overriding {@link #formSheetClosed}.</p> 130 * 131 * @override Never Instead override {@link #formSheetClosed}. 132 * 133 * @param fs the FormSheet to be closed. 134 */ 135 public void closeFormSheet(FormSheet fs) { 136 boolean fExplicit = true; 137 138 fs.detachDisplay(); 139 140 if (m_fsCurrent == fs) { 141 m_fsCurrent = null; 142 } else { 143 fExplicit = false; 144 } 145 146 formSheetClosed(); 147 148 synchronized (getWaiter()) { 149 getWaiter().notifyAll(); 150 } 151 152 fireFormSheetRemoved(fs, fExplicit); 153 } 154 155 /** 156 * Hook method called when the FormSheet was closed. 157 * 158 * @override Sometimes The default implementation closes the JDisplayDialog. 159 */ 160 protected void formSheetClosed() { 161 setVisible(false); 162 dispose(); 163 } 164 165 /** 166 * In addition to disposing of the peer resources, remove the FormSheet and the 167 * MenuSheet. 168 * 169 * @override Never 170 */ 171 public void dispose() { 172 try { 173 setFormSheet(null); 174 } 175 catch (InterruptedException e) {} 176 177 setMenuSheet(null); 178 179 super.dispose(); 180 } 181 182 /** 183 * Notification event informing about a change of a FormSheet's caption. 184 * 185 * @override Never 186 * 187 * @param fs the FormSheet whose caption changed. 188 * @param sNewCaption the new caption of the FormSheet. 189 */ 190 public void onFormSheetCaptionChanged(FormSheet fs, String sNewCaption) { 191 setTitle(sNewCaption); 192 } 193 194 /** 195 * Notification event informing about a change of a FormSheet's component. 196 * 197 * @override Never 198 * 199 * @param fs the FormSheet whose component changed. 200 * @param jcmpNew the new component of the FormSheet. 201 */ 202 public void onFormSheetComponentChanged(FormSheet fs, JComponent jcmpNew) { 203 synchronized (fs.getComponentLock()) { 204 getContentPane().remove(m_jcmpComponent); 205 206 m_jcmpComponent = fs.getComponent(); 207 if (m_jcmpComponent != null) { 208 getContentPane().add(m_jcmpComponent, BorderLayout.CENTER); 209 } 210 211 pack(); 212 } 213 } 214 215 /** 216 * Notification event informing that a button was added to the FormSheet's button bar. 217 * 218 * @override Never 219 * 220 * @param fs the FormSheet whose button bar changed. 221 * @param fb the button that was added to the FormSheet. 222 */ 223 public void onFormSheetButtonAdded(FormSheet fs, FormSheet.FormButton fb) { 224 synchronized (fs.getButtonsLock()) { 225 m_jpButtonBar.add(fb.getPeer()); 226 227 pack(); 228 } 229 } 230 231 /** 232 * Notification event informing that a button was removed from the FormSheet's button bar. 233 * 234 * @override Never 235 * 236 * @param fs the FormSheet whose button bar changed. 237 * @param fb the button that was removed from the FormSheet. 238 */ 239 public void onFormSheetButtonRemoved(FormSheet fs, FormSheet.FormButton fb) { 240 synchronized (fs.getButtonsLock()) { 241 m_jpButtonBar.remove(fb.getPeer()); 242 243 pack(); 244 } 245 } 246 247 /** 248 * Notification event informing that all buttons were removed from a FormSheet's button bar. 249 * 250 * @override Never 251 * 252 * @param fs the FormSheet whose button bar was cleared. 253 */ 254 public void onFormSheetButtonsCleared(FormSheet fs) { 255 synchronized (fs.getButtonsLock()) { 256 m_jpButtonBar.removeAll(); 257 258 pack(); 259 } 260 } 261 262 // Display interface methods 263 264 /** 265 * Set and display a FormSheet. 266 * 267 * <p>If {@link FormSheet#waitResponse fs.waitResponse()} returns true, 268 * <code>setFormSheet()</code> blocks, until the FormSheet is closed by a matching 269 * call to {@link #closeFormSheet}.</p> 270 * 271 * @override Never 272 * 273 * @param fs the FormSheet to be displayed. 274 * 275 * @exception InterruptedException if an interrupt occurs while waiting for the 276 * FormSheet to be closed. 277 */ 278 public void setFormSheet(FormSheet fs) throws InterruptedException { 279 280 if (m_fsCurrent != null) { 281 FormSheet fsTemp = m_fsCurrent; 282 283 if (fs != null) { // setFormSheet (null) will be interpreted as an explicit close, too. 284 m_fsCurrent = null; 285 } 286 287 fsTemp.cancel(); 288 } 289 getContentPane().removeAll(); 290 291 if (fs != null) { 292 synchronized (fs.getComponentLock()) { 293 synchronized (fs.getButtonsLock()) { 294 setTitle(fs.getCaption()); 295 296 fs.attach(this); 297 m_fsCurrent = fs; 298 299 m_jcmpComponent = fs.getComponent(); 300 301 if (m_jcmpComponent != null) { 302 getContentPane().add(m_jcmpComponent, BorderLayout.CENTER); 303 } 304 305 m_jpButtonBar = new JPanel(false); 306 fs.fillBtnPanel(m_jpButtonBar); 307 308 getContentPane().add(m_jpButtonBar, BorderLayout.SOUTH); 309 310 pack(); 311 } 312 } 313 314 fireFormSheetSet(fs); 315 316 if (fs.waitResponse()) { 317 synchronized (getWaiter()) { 318 while (fs.getDisplay() == this) { 319 getWaiter().wait(); 320 } 321 } 322 } 323 } 324 } 325 326 /** 327 * Return the {@link FormSheet} that is currently attached to the display. 328 */ 329 public FormSheet getFormSheet() { 330 return m_fsCurrent; 331 } 332 333 /** 334 * Close the current FormSheet. 335 * 336 * @override Never 337 */ 338 public void closeFormSheet() { 339 if (m_fsCurrent != null) { 340 closeFormSheet(m_fsCurrent); 341 } 342 } 343 344 /** 345 * Open a fresh {@link JDisplayDialog} and display the FormSheet in it. 346 * 347 * @override Never 348 * 349 * @exception InterruptedException if an interrupt occured while waiting for the 350 * FormSheet to be closed. 351 */ 352 public void popUpFormSheet(FormSheet fs) throws InterruptedException { 353 setVisible(true); 354 355 try { 356 setFormSheet(fs); 357 } 358 catch (InterruptedException e) { 359 if (fs.getDisplay() == this) { 360 fs.cancel(); 361 } 362 363 throw e; 364 } 365 } 366 367 /** 368 * Opens a fresh {@link JDisplayDialog} which is assigned to a FormSheet and displays 369 * another FormSheet in it. 370 * 371 * @override Never 372 * @param fsParent the FormSheet to which the JDisplayDialog is assigned. 373 * @param fsToSet the FormSheet which is displayed by the JDisplayDialog. 374 * 375 * @exception InterruptedException if an interrupt occured while waiting for the 376 * FormSheet to be closed. 377 */ 378 public void popUpFormSheet(FormSheet fsParent, FormSheet fsToSet) throws InterruptedException { 379 try { 380 setFormSheet(fsToSet); 381 setLocationRelativeTo(fsParent.getComponent()); 382 setVisible(true); 383 } 384 catch (InterruptedException e) { 385 if (fsToSet.getDisplay() == this) { 386 fsToSet.cancel(); 387 } 388 throw e; 389 } 390 } 391 392 /** 393 * Remove any old MenuSheet and display the new one. 394 * 395 * @override Never 396 * 397 * @param ms the MenuSheet to be displayed. 398 */ 399 public void setMenuSheet(MenuSheet ms) { 400 if (m_msCurrent != null) { 401 m_msCurrent.setVisible(false); 402 } 403 404 m_msCurrent = ms; 405 406 if (m_msCurrent != null) { 407 m_msCurrent.setVisible(true); 408 setJMenuBar(ms.getMenuBar()); 409 } else { 410 setJMenuBar(null); 411 } 412 413 pack(); 414 } 415 416 /** 417 * Return the {@link MenuSheet} that is currently attached to the display. 418 */ 419 public MenuSheet getMenuSheet() { 420 return m_msCurrent; 421 } 422 423 /** 424 * Return true to indicate this is a useable display. 425 * 426 * @override Never 427 */ 428 public boolean isUseableDisplay() { 429 return true; 430 } 431 432 /** 433 * Add a listener to receive notification on the JDisplayDialog's FormSheet. 434 * 435 * @override Never 436 */ 437 public void addFormSheetListener(FormSheetListener fsl) { 438 m_ellListeners.add(FormSheetListener.class, fsl); 439 } 440 441 /** 442 * Remove a listener to receive notification on the JDisplayDialog's FormSheet. 443 * 444 * @override Never 445 */ 446 public void removeFormSheetListener(FormSheetListener fsl) { 447 m_ellListeners.remove(FormSheetListener.class, fsl); 448 } 449 450 /** 451 * Fire an event to all {@link sale.events.FormSheetListener FormSheetListeners} indicating that 452 * a {@link FormSheet} was set on this display. As FormSheet setting is always explicit, no 453 * extra parameter is necessary. 454 * 455 * @override Never 456 * 457 * @param fs the FormSheet that was set 458 */ 459 protected void fireFormSheetSet(FormSheet fs) { 460 FormSheetEvent e = null; 461 462 Object[] listeners = m_ellListeners.getListenerList(); 463 464 for (int i = listeners.length - 2; i >= 0; i -= 2) { 465 if (listeners[i] == FormSheetListener.class) { 466 if (e == null) { 467 e = new FormSheetEvent(this, fs, true); 468 469 } 470 ((FormSheetListener)listeners[i + 1]).formSheetSet(e); 471 } 472 } 473 } 474 475 /** 476 * Fire an event to all {@link sale.events.FormSheetListener FormSheetListeners} indicating that 477 * a {@link FormSheet} was removed from this display. 478 * 479 * @override Never 480 * 481 * @param fs the FormSheet that was set 482 * @param fExplicit true, if the FormSheet was closed explicitly, i.e. either by a call to one of 483 * the <code>closeFormSheet</code> methods or by <code>setFormSheet (null)</code>. 484 * 485 * @see #closeFormSheet() 486 * @see #closeFormSheet(FormSheet) 487 * @see #setFormSheet 488 */ 489 protected void fireFormSheetRemoved(FormSheet fs, boolean fExplicit) { 490 FormSheetEvent e = null; 491 492 Object[] listeners = m_ellListeners.getListenerList(); 493 494 for (int i = listeners.length - 2; i >= 0; i -= 2) { 495 if (listeners[i] == FormSheetListener.class) { 496 if (e == null) { 497 e = new FormSheetEvent(this, fs, fExplicit); 498 499 } 500 ((FormSheetListener)listeners[i + 1]).formSheetRemoved(e); 501 } 502 } 503 } 504 505 /** 506 * JDisplayDialog test suite. 507 */ 508 public static void main(java.lang.String[] args) { 509 final JDisplayDialog jdd = new JDisplayDialog(); 510 jdd.setVisible(true); 511 512 MenuSheet ms = new MenuSheet("Main"); 513 ms.add(new MenuSheetItem("Quit", new Action() { 514 private static final long serialVersionUID = 2734448317849130419L; 515 public void doAction(SaleProcess p, SalesPoint sp) { 516 jdd.dispose(); 517 } 518 })); 519 520 jdd.setMenuSheet(ms); 521 522 final MsgForm mfTest = new sale.stdforms.MsgForm("Testmessage", 523 "Dies ist ein Test des JFormSheetFrames.\n\n" + 524 "Wir verwenden dazu ein veraendertes MsgForm."); 525 526 mfTest.addButton("Toggle Caption", 1, new Action() { 527 private static final long serialVersionUID = 3661359200322902803L; 528 public void doAction(SaleProcess p, SalesPoint sp) { 529 if (mfTest.getCaption().equals("Testmessage")) { 530 mfTest.setCaption("Geaendert !"); 531 } else { 532 mfTest.setCaption("Testmessage"); 533 } 534 } 535 }); 536 537 mfTest.addButton("Add button", 2, new Action() { 538 private static final long serialVersionUID = -6514280491544062500L; 539 public void doAction(SaleProcess p, SalesPoint sp) { 540 mfTest.addButton("Tester", 700, null); 541 mfTest.getButton(2).setEnabled(false); 542 mfTest.getButton(3).setEnabled(true); 543 } 544 }); 545 546 mfTest.addButton("Remove button", 3, new Action() { 547 private static final long serialVersionUID = -4483019927000420030L; 548 public void doAction(SaleProcess p, SalesPoint sp) { 549 mfTest.removeButton(700); 550 mfTest.getButton(2).setEnabled(true); 551 mfTest.getButton(3).setEnabled(false); 552 } 553 }); 554 mfTest.getButton(3).setEnabled(false); 555 556 final JComponent[] ajcmp = new JComponent[1]; 557 ajcmp[0] = new JLabel("Tester"); 558 559 mfTest.addButton("Toggle Component", 4, new Action() { 560 private static final long serialVersionUID = -7835577623326127041L; 561 public void doAction(SaleProcess p, SalesPoint sp) { 562 ajcmp[0] = mfTest.setComponent(ajcmp[0]); 563 } 564 }); 565 566 try { 567 jdd.setFormSheet(mfTest); 568 } 569 catch (InterruptedException e) {} 570 571 System.err.println("FormSheet was " + ((mfTest.isCancelled()) ? ("cancelled.") : ("closed normally."))); 572 573 System.exit(0); 574 } 575 576 public void load(ObjectInputStream ois) throws IOException, ClassNotFoundException {} 577 578 public void save(ObjectOutputStream oos) throws IOException {} 579 580 }