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