001/*
002 * MDIApplet.java
003 * Copyright (c) 2002 Tom B. Gutwin P.Eng.
004 *
005 * This program is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU General Public License
007 * as published by the Free Software Foundation; either version 2
008 * of the License, or any later version.
009 *
010 * This program 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
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program; if not, write to the Free Software
017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
018 */
019
020/*
021$Header: f:/cvsroot2/open/projects/WebARTS/ca/bc/webarts/MDIApplet.java,v 1.1 2002/07/11 06:17:23 tgutwin Exp $
022 *
023$Log: MDIApplet.java,v $
024Revision 1.1  2002/07/11 06:17:23  tgutwin
025Initial Revision
026
027Revision 1.4  2001/03/11 23:33:46  tgutwin
028Added the basics for creating the internal windows
029
030Revision 1.3  2001/03/03 07:30:44  tgutwin
031Added Button Processing logic & some general Cleanup
032
033Revision 1.2  2001/02/24 07:43:35  tgutwin
034Added CVS Header
035
036 */
037/* Generic MDI app/let */
038/* - Tom B. Gutwin - */
039/* Copyright 2001 - WebARTS Design */
040
041
042/* This program requires JVM 1.2 or at least JVM 1.1.5 with
043 * the Swing 1.1.1 components */
044/* If building with the OS/2 JDK you must have at least 1.1.4
045 * with the 1.1.4 fixes */
046
047package ca.bc.webarts;
048
049import ca.bc.webarts.widgets.Splash;
050import ca.bc.webarts.widgets.StatusBar;
051import ca.bc.webarts.widgets.AutoButtonBar;
052import ca.bc.webarts.widgets.JAboutBox;
053
054import java.awt.*;
055import java.awt.event.*;
056import java.awt.image.*;
057import java.net.*;
058import java.applet.*;
059import javax.swing.*;
060import java.lang.Class;
061import java.awt.event.ActionListener;
062import javax.swing.border.*;
063
064/**
065 *  MDIApplet encapsulates a generic and extendable framework for a multiple
066 *  desktop interface application.
067 *
068 * <P><B>This applet has a main() method so it can be directly called/started
069 * as an application.</B>
070 *
071 * <P>It contains all the basics of an <I>Multiple Document Interface (MDI)</I>
072 * windowing system with a Menubar at the top, a floatable toolbar, and a
073 * statusbar at the bottom. In the center of the applet is the main MDI Desktop.
074 *
075 * <P>New child windows all go into the main MDI Desktop panel and each contain
076 * a generic <code>Object</cose>.
077 *
078 * @author <A HREF="http://www.webarts.bc.ca">Tom Gutwin</A>
079 *
080 * @created    December 13, 2000
081 */
082public class MDIApplet extends JApplet implements ActionListener{
083
084  /**
085   *  Holds the line separator for the system this applet is running on.
086   */
087  String lineSeperator = new String(System.getProperty("line.separator"));
088
089  /**
090   *  Holds the file separator for the system this applet is running on.
091   */
092  String fileSeperator = new String(System.getProperty("file.separator"));
093
094  /**
095   *  The Toolkit object that is used to get some basic system information (ie screen size).
096   */
097  Toolkit toolkit = Toolkit.getDefaultToolkit();
098
099  /**
100   *  String added to the iconNames used to auatomatically
101   *  create the IconsBar
102   */
103  String  iconNamePrefix = "../images/20x20";
104
105  /**
106   *  String Tokens used to auatomatically create the IconsBar
107   */
108  String  iconNames[] = {"Exit.gif", "Open.gif", "Computer.gif", "Help.gif"};
109
110    /**
111   *  String Tokens used to auatomatically create the Icon bar tooltips
112   */
113  String iconToolTips[] = {"Exit This App", "Open Something", "Computer??", "Help!"};
114
115  /**
116   *  String Tokens used to auatomatically create the menu bar
117   */
118  String menuName[] = {"File", "View", "Properties", "Help"};
119
120  /**
121   *  String Tokens used to automatically create the menu items for each menu
122   *  on the menubar.  It is a 2D array of strings that will be used to create
123   *  menuitems.  If there are 4 menus... there will be 4 lists holding the
124   *  words/Strings to use for the menu items.
125   */
126  String menuItemName[][] = {
127      {"Open", "Save", "---", "Print...", "Print Preview", "---", "Close", "Exit"},
128      {"Zoom In", "Zoom Out" },
129      {"Set Debug Output Level...", "---",
130       "Java L&F", "Platform L&F", "Motif L&F" },
131      {"Help", "---", "About MDIApplet..."}};
132
133  /**
134   *  The Tokens used to automatically assign the Mnemonic for each menu items.
135   *  It is a 2D array of chars that will be used to assign the Mnemonic.
136   *  If there are 4 menus... there will be 4 lists holding the chars to use
137   *  as the Mnemonic for the menu items.
138   */
139  char menuItemMnemonic[][] = {
140      {'o', 's', ' ', 'P', 'r', ' ', 'C', 'x'},
141      {'I', 'O'},
142      {'D', ' ', 'J', 'P', 'M'},
143      {'H', ' ', 'A'}};
144
145  /**
146   *  The Tokens used when automatically assigning the accel key for each menu
147   *  items.  It is a 2D array of ints that will be used to assign the accel
148   *  key constant.  If there are 4 menus... there will be 4 lists holding the
149   *  ints to use as the accel key constant value for the menu items.
150   */
151  int menuItemAccel[][] = {
152      {KeyEvent.VK_O, KeyEvent.VK_S, 0,
153       KeyEvent.VK_A, KeyEvent.VK_B, 0,
154       KeyEvent.VK_W, KeyEvent.VK_Q},
155      {0, 0 },
156      {0, 0, 0, 0, 0},
157      {KeyEvent.VK_F1, 0, KeyEvent.VK_F12}};
158
159  /**
160   * The Tokens used when automatically assigning the 2nd level of accel key for
161   * each menu items. It is a 2D array of ints that will be used to assign the
162   * accel key constant.  If there are 4 menus... there will be 4 lists holding
163   * the ints to use as the accel key constant value for the menu items.
164   */
165  int menuItemAccel2[][] = {
166      {Event.CTRL_MASK, Event.CTRL_MASK, 0, Event.CTRL_MASK | Event.SHIFT_MASK, Event.CTRL_MASK |
167       Event.SHIFT_MASK, 0, Event.CTRL_MASK, Event.CTRL_MASK},
168      {0, 0},
169      {0, 0, 0, 0, 0},
170      {0, 0, 0}};
171
172  /**
173   *  String Tokens used to automatically create the menu items tooltip for
174   *  each menu on the menubar. It is a 2D array of strings that will be used
175   *  to create menuitems tooltips.  If there are 4 menus...  there will be 4
176   *  lists holding the words/Strings to use for the menu items tooltip.
177   */
178  String menuToolTip[][] = {{"Open new window from File...", "Save Current Windows Output To File...", "---", "Print Current Authorization View", "Print Preview", "---", "Close Current Window", "Exit Application"},
179      {"Zoom In", "Zoom Out"},
180      {"Set Debug Output Level...", "---", "Set the User Interface to the Java-Metal L&F", "Set the User Interface to the Platform L&F", "Set the User Interface to the Motif L&F", "---", "Sets the 2nd Segment to be be designated as the START Segment", "Sets the 3rd Segment to be be designated as the START Segment"},
181      {"Help On This Applet", "---", "About MDIApplet..."}};
182
183  /**
184   *  boolean Tokens used to enable automatic creation of the menu items for
185   *  each menu on the menubar. It is a 2D array of booleans each one a flag
186   *  directly refering to the menu item arrays already setup. If there are 4
187   *  menus... there will be 4 lists holding the flags to use. If a value of
188   *  false is specified the menu item will NOT get created.
189   */
190  static boolean menuItemShown[][] = {
191      {true, true, true, true, true, true, true, true},
192      {true, true},
193      {true, true, true, true, true},
194      {true, true, true}};
195
196  /**
197   *  boolean Tokens used to enable the menu items for each menu on the menubar.
198   *  It is a 2D array of booleans each one a flag directly refering to the
199   *  menu item arrays already setup. If there are 4 menus... there will be 4
200   *  lists holding the flags to use. If a value of false is specified the menu
201   *  item will be grayed.
202   */
203  static boolean menuItemEnabled[][] = {
204      {true, true, true, true, true, true, true, true},
205      {true, true},
206      {true, true, true, true, true},
207      {true, true, true}};
208
209  /**
210   *  The applets JToolbar.
211   */
212  private AutoButtonBar myButtonBar;
213
214  /**
215   *  The Applets MenuBar. It gets initialized by the method
216   *  <code>initMenuBar</code>.
217   * @see initMenuBar
218   */
219  private JMenuBar menuBar;
220
221  /**
222   *  A status bar object that lives at the bottom of the Internal Window
223   *  Desktop to provide useful information regarding the applet.
224   */
225  private StatusBar statBar;
226
227  /**
228   *  Status bar information variable used with the StatusBar object.
229   *  It provides the sizes for the different sections of the status bar
230   *
231   * @see    <code>StatusBar</code>
232   */
233  private double[] statusSizes = {0.6, 0.2, 0.1, 0.1};
234
235  /**
236   *  Status bar information variable used with the StatusBar object.
237   *  It provides the initial Strings for the different sections of the
238   *  status bar
239   *
240   * @see    <code>StatusBar</code>
241   */
242  private String[] statusMsg = {"StatusArea0", "StatusArea1",
243                                "StatusArea2", "Status Area 3"};
244
245/**
246 * The Applets main internal window desktop panel.
247   *  A JPanel that will hold desktop that is going into this
248   *  applet EXCEPT the statusbar and menubar; this is so the status bar is at
249   *  the bottom of the applet, the menubar stays at the top and everything
250   *  else is in between.  See the start method that sets it all up.
251 */
252  private JPanel        mdiPanel = new JPanel();
253
254/**
255 * The Applets main desktop object manager.
256 */
257 private DesktopController desktopController;
258
259/**
260 * myMDIDesktop is the Multiple Document Desktop that gets placed directly
261 * inside the MDIViewPanel JPanel. It will hold all the child windows for
262 * this app.
263 */
264  private JLayeredPane myMDIDesktop;
265
266
267
268/**
269 * The initial X coordinate for this app/let.
270 */
271  private short   appX = 10;
272
273/**
274 * The initial Y coordinate for this app/let.
275 */
276  private short  appY = 10;
277
278  /**
279   *  The Codes Base URL.
280   */
281  private URL codeBase;
282
283  /**
284   *  A flag that indicates if this applet is running as an application.
285   */
286  public static boolean isRunningAsAnApplet = true;
287
288  /**
289   *  Suffix applied to the key used in resource file
290   *  lookups for an image.
291   */
292  public final static String imageSuffix = "Image.gif";
293
294  /**
295   *  Suffix applied to the key used in resource file
296   *  lookups for an action.
297   */
298  public final static String actionSuffix = "Action";
299
300  /**
301  * The filename for the graphic to splash up at start
302 */
303  private static final String splashGraphic = "../images/DONT_PAN.GIF"  ;
304
305  /**
306   *  The Current Date and time.
307   */
308  static java.util.Date currentDate;
309
310  /**
311   *  Flag to spew debug output to the screen.
312   */
313  static boolean debugOutput = false;
314
315  /**
316   *  the Metal LookAndFeel CONSTANT.
317   */
318   public static final short METAL_LOOKANDFEEL = 0;
319
320  /**
321   *  the Windoze LookAndFeel CONSTANT.
322   */
323   public static final short WINDOZE_LOOKANDFEEL = 1;
324
325  /**
326   *  the Motif LookAndFeel CONSTANT.
327   */
328   public static final short MOTIF_LOOKANDFEEL = 2;
329
330  /**
331   *  the Mac LookAndFeel CONSTANT.
332   */
333   public static final short MAC_LOOKANDFEEL = 3;
334
335  /**
336   *  the Default LookAndFeel CONSTANT. DEFAULT_LOOKANDFEEL = METAL_LOOKANDFEEL
337   */
338   public static final short DEFAULT_LOOKANDFEEL = METAL_LOOKANDFEEL;
339
340  /**
341   *  The CONSTANT to represent LEFT screen justification.
342   *  Used in the setScreenLocation method.
343   */
344   public static final short LEFT_SCREENJUSTIFY = -1;
345
346  /**
347   *  The CONSTANT to represent CENTER screen justification.
348   *  Used in the setScreenLocation method.
349   */
350   public static final short CENTER_SCREENJUSTIFY = -2;
351
352  /**
353   *  The CONSTANT to represent RIGHT screen justification.
354   *  Used in the setScreenLocation method.
355   */
356   public static final short RIGHT_SCREENJUSTIFY = -3;
357
358  /**
359   *  The CONSTANT to represent TOP screen justification.
360   *  Used in the setScreenLocation method.
361   */
362   public static final short TOP_SCREENJUSTIFY = -4;
363
364  /**
365   *  The CONSTANT to represent BOTTOM screen justification.
366   *  Used in the setScreenLocation method.
367   */
368   public static final short BOTTOM_SCREENJUSTIFY = -5;
369
370  /**
371   *  the Mac LookAndFeel class name
372   */
373  private static String macClassName =
374      "com.sun.java.swing.plaf.mac.MacLookAndFeel";
375  /**
376   *  the Java LookAndFeel class name
377   */
378  private static String metalClassName =
379      "javax.swing.plaf.metal.MetalLookAndFeel";
380  /**
381   *  the motif LookAndFeel class name
382   */
383  private static String motifClassName =
384      "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
385  /**
386   *  the Windoze LookAndFeel class name
387   */
388  private static String windowsClassName =
389      "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
390
391  /**
392   *  A holder for a string representation of the users starting directory.
393   */
394  private static String userDir = "";
395
396  /**
397   *  General variables that are used as counters or temps.
398   */
399  private static String tempPath;
400
401  /**
402   *  Strings to hold the retrieved applet parameters. They are initialized
403   *  to their default values.
404   */
405  private static String mediaURL = "file:///c|/movie.mov";
406
407  /**
408   *  A variable to indicate the level of debug output produced.
409   *  debug = 0 is OFF
410   *  debug = 1 is Minimal Output
411   *  debug = 2 is General Outline of Programs Position
412   *  debug = 3 is Detailed Object creation and method location
413   *  debug = 4 is verbose
414   */
415  private static int debug = 3;
416
417  /**
418   *  A temp variable that holds the APPLET parameter that might or might not
419   *  have been specified at runtime.
420   *  This value (if the user specified a value at Init) gets transfered
421   *  into debug.
422   */
423  private static int debugParam = 1;
424
425
426  /**
427   *  the method that return the programmers customized information about
428   *  this applet.
429   *
430   * @return    The AppletInfo value
431   */
432  public String getAppletInfo() {
433    return "Generic MDI Desktop. Copyright (c) WebARTS Design 2001 - Tom Gutwin P.Eng.";
434  }
435
436
437  /**
438   *  The method that returns the information about the possible applet
439   *  parameters.
440   *
441   * @return    a table of Strings (String[][]) holding the input param
442   *            name, type and description
443   */
444  public String[][] getParameterInfo() {
445    String[][] retVal = {
446        {"DEBUG", "int", "specifies the level of debug output; 0=off; " +
447         "1=minor; 2=medium; 3=verbose; default = 1"},
448        {"MEDIAURL", "String", "the string that indicates the filename to " +
449         "initially open up; DEFAULT = nothing"}
450        };
451    return retVal;
452  }
453
454
455  /**
456   *  Tells if this applet was started as an app via its main method
457   *
458   * @return    The App value
459   */
460  public boolean isApp() {
461    return (!isRunningAsAnApplet);
462  }
463
464
465  /**
466   *  Tells if this applet was started as an applet directly without
467   *  going through its main method.
468   *
469   * @return    The Applet value
470   */
471  public boolean isApplet() {
472    return (isRunningAsAnApplet);
473  }
474
475  /**
476   * Receives the button actions
477   */
478public void actionPerformed(ActionEvent e)
479{
480    int butInx = buttonIndexOf(iconToolTips,
481                 ((JButton)e.getSource()).getToolTipText());
482    debugOutput(3,"ActionEvent.... "+butInx);
483    switch (butInx )
484    {
485      case 0:
486        debugOutput(3, " Exit Pressed "  );
487        /* now add the specific stuff for this button */
488        stop();
489        System.exit(0);
490        break;
491      case 1:
492        break;
493      case 2:
494        break;
495      case 3:
496        break;
497      default:
498    }
499}
500
501
502  /**
503   *  Initializes the Applet. Gets all the initial data read in and set up.
504   */
505  public void init() {
506    setVisible(false);
507    System.out.println("Into Init....");
508
509    /* get the JApplets root pane & make a fix so this
510       applet does not crash NS or IE */
511    JRootPane rp = getRootPane();
512    rp.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
513
514    try {
515      if (isRunningAsAnApplet) {
516        /* Get The Code Base */
517        codeBase = new URL(getCodeBase().toString());
518
519        /* Get the input parameters */
520        debugParam = (new Integer(getParameter("DEBUG"))).intValue();
521
522        mediaURL = getParameter("MEDIAURL");
523      }
524      else {
525        getAppCodeBase();
526      }
527    }
528    catch (java.net.MalformedURLException t) {
529      System.out.println("caught java.net.MalformedURLException: " + t +
530                         "Cannot retrieve codebase");
531      t.printStackTrace();
532    }
533
534    /* Force SwingSet to come up in the Cross Platform L&F */
535    setTheLookAndFeel(METAL_LOOKANDFEEL);
536
537    /* set the layout manager for correct spacing */
538    getContentPane().setLayout(new BorderLayout());
539
540    /* create the statusbar */
541    debugOutput(1, "Creating StatusBar...");
542    statBar = initStatusBar();
543
544    /* create the scroll pane that is going to go into the frame */
545    mdiPanel.setBorder(BorderFactory.createEtchedBorder());
546    mdiPanel.setLayout(new BorderLayout());
547
548    /* create the menu bar */
549    menuBar = initMenuBar();
550
551    /* create the button bar */
552    debugOutput(2, "Creating ToolBar...");
553//    myButtonBar = new AutoButtonBar(mdiPanel, statBar, codeBase);
554    myButtonBar = new AutoButtonBar(codeBase);
555    myButtonBar.setIcons(iconNames, iconToolTips);
556    myButtonBar.setController( this);
557    myButtonBar.setRelImageLocator(iconNamePrefix);
558    myButtonBar.createButtons();
559    myButtonBar.setFloatable(true);
560
561  }
562
563
564/**
565 *  Starts the operation of the applet.
566 *  It gets everything running by performing the following functions:
567 *  <UL><LI><B>adds all the objects to the applet</B>
568 *  <LI><B>opens up an initial desktopController that is the child window
569 *        supervisor/B>
570 *  <LI><B>sets location of the applet on the screen</B>
571 *  <LI><B>then its SHOWTIME!</B>
572 *  </UL>
573 *  The way things are laid out in the applet are as follows:
574 *  the media JPanel will hold everything that is going into this applet EXCEPT
575 *  the statusbar and menubar;
576 *  This is so the status bar stays at the bottom of the applet and the menubar
577 *  stays at the top with the menubar able to float around the actual Internal
578 *  Window desktop.
579 */
580  public void start() {
581    System.out.println("Into Start....");
582
583    /* add the button control button panel & deskTopController to the MdiPanel */
584    mdiPanel.add(myButtonBar, "North");
585    desktopController = new DesktopController(null);
586    JScrollPane scroller = new JScrollPane(
587                              JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
588                              JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
589    scroller.setBorder(new BevelBorder(BevelBorder.LOWERED));
590
591    scroller.getViewport().add(desktopController);
592//    setContentPane(desktopController);
593    mdiPanel.add(scroller, "Center");
594
595    /* add the StatusBar to the bottom of the applet window */
596    debugOutput(3, "Adding the StatusBar Panel....");
597    getContentPane().add(statBar, "South");
598
599    /* add the MenuBar to the Top of the applet window */
600    debugOutput(3, "Adding the MenuBar Panel....");
601    getContentPane().add(menuBar, "North");
602
603    /* add the Desktop Area to the applet window */
604    getContentPane().add(mdiPanel, "Center");
605
606    if (isRunningAsAnApplet) {
607      /* set out the applets position on the screen */
608      setScreenLocation(CENTER_SCREENJUSTIFY, CENTER_SCREENJUSTIFY, 0, 0);
609    }
610    validate();
611
612    setVisible(true);
613  }
614
615
616  /**
617   *  The stop method that gets called whne stoping the applet.
618   *  It does clean up.
619   */
620  public void stop() {
621    System.out.println("Stopping....");
622    remove(statBar);
623    remove(menuBar);
624    remove(mdiPanel);
625  }
626
627
628  /**
629   * Initializes the statusbar with the pre- inititialized arrays of data.
630   */
631   private StatusBar initStatusBar() {
632    StatusBar statBar;
633
634    statBar = new StatusBar(statusSizes.length, statusSizes, statusMsg);
635    statBar.updateBackgroundColour(0, new Color(210, 180, 210));
636    for (int i=0; i< statusSizes.length; i++) {
637      statBar.updateFont(i, new Font("Arial", Font.PLAIN, 9));
638    }
639    return statBar;
640   }
641
642
643  /**
644   *  Forces a repaint to this apps menubar.
645   */
646  public void repaintMenuBar() {
647    if (menuBar != null) {
648      menuBar.repaint();
649    }
650  }
651
652
653  /**
654   *  Calls the User Interface Manager and sets the look and feel setting based
655   *  on the parameter it is passed.
656   *
657   * @param  i   The new TheLookAndFeel value
658   */
659  private void setTheLookAndFeel(short i) {
660    /* Force SwingSet to come up in the Cross Platform L&F */
661    try {
662      switch ((int)i){
663        case METAL_LOOKANDFEEL:
664          // If you want the Java L&F
665          UIManager.setLookAndFeel(metalClassName);
666          debugOutput(3, "Setting the Java L&F");
667          break;
668        case WINDOZE_LOOKANDFEEL:
669          // If you want the System L&F
670          UIManager.setLookAndFeel(windowsClassName);//UIManager.getSystemLookAndFeelClassName());
671          debugOutput(3, "Setting the System L&F");
672          break;
673        case MOTIF_LOOKANDFEEL:
674          // If you want the Motif L&F
675          UIManager.setLookAndFeel(motifClassName);
676          debugOutput(3, "Setting the Motif L&F");
677          break;
678        case MAC_LOOKANDFEEL:
679          // If you want the Mac L&F
680          UIManager.setLookAndFeel(macClassName);
681          debugOutput(3, "Setting the Mac L&F");
682          break;
683        default:
684          // defaults to Java L&F
685          UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
686          debugOutput(3, "Setting the Java L&F");
687      }
688      SwingUtilities.updateComponentTreeUI(getAncestorFrame(this));
689    }
690    catch (Exception exc)
691    {
692      System.err.println("Error loading L&F: " + exc);
693    }
694  }
695
696
697
698  /**
699   *  This method sets the position of this app/applet on the users screen
700   *  based on the supplied location parameters
701   *
702   * @param  xPosition   The new ScreenLocation value
703   * @param  yPosition   The new ScreenLocation value
704   * @param  xOffset     The new ScreenLocation value
705   * @param  yOffset     The new ScreenLocation value
706   */
707  private void setScreenLocation(int xPosition, int yPosition,
708                                 int xOffset,   int yOffset) {
709    /* the xPosition can be -1,-2, or -3 for left center and right justified */
710    /* the yPosition can be -4,-2, or -5 for Top center and bottom justified */
711
712    Dimension scrnSize = toolkit.getScreenSize();
713    Frame topFrame = getAncestorFrame((Component) this);
714    int scrnWidth = scrnSize.width;
715    int
716        scrnHeight = scrnSize.height;
717    int frameWidth = topFrame.getSize().width;
718    int
719        frameHeight = topFrame.getSize().height;
720    Point startPoint = topFrame.getLocationOnScreen();
721    Point newPoint = new Point(startPoint);
722
723    debugOutput(3, "Existing pos       " +
724        " " + (new Integer(xPosition)).toString() +
725        " " + (new Integer(yPosition)).toString() +
726        " " + (new Integer(frameWidth)).toString() +
727        " " + (new Integer(frameHeight)).toString() +
728        " " + (new Integer(newPoint.x)).toString() +
729        " " + (new Integer(newPoint.y)).toString());
730
731    switch (xPosition)
732    {
733      case LEFT_SCREENJUSTIFY:
734        newPoint.x = 0 + xOffset;
735        break;
736      case CENTER_SCREENJUSTIFY:
737        newPoint.x = scrnWidth / 2 - frameWidth / 2 + xOffset;
738        break;
739      case RIGHT_SCREENJUSTIFY:
740        newPoint.x = scrnWidth - frameWidth;
741        break;
742      default:
743        debugOutput(3, "Setting an Absolute X Screen Location");
744        newPoint.x = xPosition + xOffset;
745    }
746    switch (yPosition)
747    {
748      case TOP_SCREENJUSTIFY:
749        newPoint.y = 0 + yOffset;
750        break;
751      case CENTER_SCREENJUSTIFY:
752        newPoint.y = scrnHeight / 2 - frameHeight / 2 + yOffset;
753        break;
754      case BOTTOM_SCREENJUSTIFY:
755        newPoint.y = scrnHeight - frameHeight;
756        break;
757      default:
758        debugOutput(3, "Setting an Absolute Y Screen Location");
759        newPoint.y = yPosition + yOffset;
760    }
761    debugOutput(3, "NEW pos            " +
762        " " + (new Integer(xPosition)).toString() +
763        " " + (new Integer(yPosition)).toString() +
764        " " + (new Integer(frameWidth)).toString() +
765        " " + (new Integer(frameHeight)).toString() +
766        " " + (new Integer(newPoint.x)).toString() +
767        " " + (new Integer(newPoint.y)).toString());
768    topFrame.setLocation(newPoint);
769  }
770
771
772  /**
773   *  Creates a URL for the location of the applications codebase.
774   */
775  private void getAppCodeBase() {
776    /* because this is an application the codebase does not work */
777    /* we have to create the codeBase URL from the userDir */
778    int i = 0;
779    debugOutput(3, "userdir=" + userDir);
780
781    try {
782      /* 1st test if this is a DOS/OS/2 style path with a drive letter */
783      if (userDir.charAt(1) == ':')
784      {
785        tempPath = userDir.substring(0, 1);
786        tempPath += ":";
787        /* Replace the file separators with the forward slash */
788        for (i = 2; i <= userDir.length() - 1; i++) {
789          if (userDir.charAt(i) != fileSeperator.charAt(0)) {
790            tempPath += userDir.substring(i, i + 1);
791          }
792          else {
793            tempPath += "/";
794          }
795        }
796        codeBase = new URL("FILE:/" + tempPath + "/");
797      }
798      else{
799        /* 2nd test if this is a UN*x style path without a drive letter */
800        if (userDir.charAt(0) == '/') {
801          debugOutput(3, "Appears to be a Unix filesystem");
802          codeBase = new URL("FILE:" + userDir + "/");
803        }
804        else {
805          codeBase = new URL("FILE:/./");
806        }
807      }
808      debugOutput(3, "APP codeBase=" + codeBase.toString());
809    }
810    catch (java.net.MalformedURLException t) {
811      System.out.println("caught java.net.MalformedURLException: " + t +
812                         "Cannot retrieve User Directory");
813      t.printStackTrace();
814    }
815    catch (StringIndexOutOfBoundsException t)
816    {
817      System.out.println("caught StringIndexOutOfBoundsException: " + t +
818                         "Cannot retrieve User Directory");
819      t.printStackTrace();
820    }
821  }
822
823
824  /**
825   *  This method seeks out and returns the Parent Frame for a given component.
826   *
827   * @param  c  The Component to be used as the basis of the frame search
828   * @return    Frame The Frame that eventually holds the giuven Component.
829   */
830  private Frame getAncestorFrame(Component c) {
831    Frame retVal = null;
832    while ((c = c.getParent()) != null)
833      if (c instanceof Frame) {
834        retVal = (Frame) c;
835      }
836    return retVal;
837  }
838
839
840  /**
841   *  Creates the JMenuBar and populates the menuitms into it.
842   *  It uses a set of predefined String arrays that it loops through to create
843   *  the menus. This way the menus can be easily changed by simply adding or
844   *  removing entrys in the arrays. You can set the name, Accelerator,
845   *  Mnemonic, Tooltip, enabled/disabled (clickable/gray), and even if the
846   *  item gets created at all!
847   *  <P>The fields it uses are:
848   *  <UL>
849   *  <LI>menuItemShown
850   *  <LI>menuName
851   *  <LI>menuItemName
852   *  <LI>menuItemAccel
853   *  <LI>menuItemAccel2
854   *  </UL>
855   *
856   * @return    JMenuBar
857   * @see       MediaViewer#createMenuItem(int,int)
858   */
859  private JMenuBar initMenuBar() {
860    int i;
861    int j;
862    JMenu tempMenu;
863    JMenuBar tempMenuBar;
864
865    tempMenuBar = new JMenuBar();
866
867    for (i = 0; i < menuName.length; i++) {
868      tempMenu = new JMenu(menuName[i]);
869      for (j = 0; j < menuItemName[i].length; j++)
870        if (menuItemShown[i][j])
871          if (menuItemName[i][j].equals("---"))
872            tempMenu.addSeparator();
873          else
874            /* Use the HELPER function called *createMenuItem* to actually do
875              the menuItem Object creation */
876            if (menuItemAccel[i][j] != 0)
877              tempMenu.add(createMenuItem(i, j)).setAccelerator(
878                           KeyStroke.getKeyStroke(menuItemAccel[i][j],
879                           menuItemAccel2[i][j]));
880            else
881              tempMenu.add(createMenuItem(i, j));
882      tempMenuBar.add(tempMenu);
883    }
884    return tempMenuBar;
885  }
886
887
888  /**
889   *  This is the hook through which all menu items are created.
890   *  The fields it uses are:
891   *  <UL>
892   *  <LI>menuItemMnemonic
893   *  <LI>menuToolTip
894   *  <LI>menuItemEnabled
895   *  </UL>
896   *
897   * @param  menuRef       Description of Parameter
898   * @param  menuItemRef   Description of Parameter
899   * @return               Description of the Returned Value
900   * @see                  MediaViewer#createMenu()
901   */
902  private JMenuItem createMenuItem(int menuRef, int menuItemRef) {
903
904    String cmd = menuItemName[menuRef][menuItemRef];
905    JMenuItem mi = new JMenuItem(menuItemName[menuRef][menuItemRef]);
906    mi.setMnemonic(menuItemMnemonic[menuRef][menuItemRef]);
907    try {
908      URL url = new URL(codeBase, "images" + fileSeperator +
909                        menuItemName[menuRef][menuItemRef] + imageSuffix);
910      mi.setHorizontalTextPosition(JButton.RIGHT);
911      mi.setIcon(new ImageIcon(url));
912    }
913    catch (java.net.MalformedURLException t) {
914      debugOutput(3, "caught exception: " + t +
915                     "Cannot retrieve Menu Item image");
916    }
917
918    mi.setToolTipText(menuToolTip[menuRef][menuItemRef]);
919    mi.setEnabled(menuItemEnabled[menuRef][menuItemRef]);
920    /* call the one size fits all method to add the appropriate
921      listener to this menu item */
922    addListener(mi);
923    return mi;
924  }
925
926
927  /**
928   *  Aa simple indexOf helper function to look through the menu items and
929   *  return an int to represent its HASH position
930   *
931   * @param  s       Description of Parameter
932   * @return         int A value that is the HASH in the menuItem array for
933   *                 the menuItem passed in as a param
934   */
935  private int indexOf(String s) {
936    int i;
937    int j;
938    int retVal = 0;
939    for (j = 0; j < menuName.length; j++){
940      for (i = 0; i < menuToolTip[j].length; i++) {
941        try {
942          if (s.equals(menuToolTip[j][i])) {
943            i = menuToolTip[j].length - 1;
944            j = menuName.length - 1;
945          }
946          else {
947            retVal++;
948          }
949        }
950        catch (java.lang.ArrayIndexOutOfBoundsException t) {
951          debugOutput(3, "caught exception: " + t + "Index =" +
952             (new Integer(j)).toString() + "," + (new Integer(i)).toString());
953        }
954      }
955    }
956    return retVal;
957  }
958
959  /**
960   *  Aa simple indexOf helper function to look through the button items and
961   *  return an int to represent its HASH position
962   *
963   * @param  list    List of strings to look through
964   * @param  s       Description of Parameter
965   * @return         int A value that is the HASH in the menuItem array for
966   *                 the menuItem passed in as a param
967   */
968  private int buttonIndexOf(String[] list, String s) {
969    int i;
970    int retVal = 0;
971    debugOutput(3, "buttonIndexOf: " + list[0] + s);
972      for (i = 0; i < list.length; i++) {
973        try {
974          if (s.equals(list[i])) {
975            i = list.length - 1;
976          }
977          else {
978            retVal++;
979          }
980        }
981        catch (java.lang.ArrayIndexOutOfBoundsException t) {
982          debugOutput(3, "caught exception: " + t + "Index =" +
983             (new Integer(i)).toString() + "," + (new Integer(i)).toString());
984        }
985      }
986    return retVal;
987  }
988
989
990  /**
991   *  Adds an ActionListener to the JMenuItem that is supplied in the
992   *  passed param. This method SHOULD be overriden by the extending
993   *  class to enable its specific fuctionality.
994   * @param  menuItem  The feature to be added to the Listener attribute
995   */
996  private void addListener(JMenuItem menuItem) {
997    /* use a simple indexOf helper function to look through the menu
998       items and return an int to represent its HASH position */
999    debugOutput(4, " Adding a listener for menu item " +
1000                menuItem.getToolTipText() + " " +
1001                indexOf(menuItem.getToolTipText())
1002    );
1003    switch (indexOf(menuItem.getToolTipText()))
1004    {
1005      case 0:
1006        /* Open Window Data To File */
1007        menuItem.addActionListener(
1008          new ActionListener()
1009          {
1010            /**
1011             *  Description of the Method
1012             *
1013             * @param  event  Description of Parameter
1014             */
1015            public void actionPerformed(ActionEvent event) {
1016              repaintMenuBar();
1017              /* now add the specific stuff for this Menu Item */
1018              try
1019              {
1020                desktopController.makeNewChildWindow();
1021                desktopController.addWindowContent(
1022                           new JTextArea("EMPTY BOX"));
1023              }
1024              catch (Exception ex)
1025              {
1026                debugOutput(3, "caught exception: " + ex);
1027            //    ex.printStackTrace();
1028              }
1029            }
1030            /* action performed */
1031          });
1032        break;
1033
1034      case 1:
1035        /* Save Window Data To File */
1036        menuItem.addActionListener(
1037          new ActionListener()
1038          {
1039            /**
1040             *  Description of the Method
1041             *
1042             * @param  event  Description of Parameter
1043             */
1044            public void actionPerformed(ActionEvent event) {
1045              repaintMenuBar();
1046              /* now add the specific stuff for this Menu Item */
1047            }
1048            /* action performed */
1049          });
1050        break;
1051
1052      case 3:
1053        /* print */
1054        menuItem.addActionListener(
1055          new ActionListener()
1056          {
1057            /**
1058             *  Description of the Method
1059             *
1060             * @param  event  Description of Parameter
1061             */
1062            public void actionPerformed(ActionEvent event) {
1063              repaintMenuBar();
1064              debugOutput(3, " PRINT MenuItem Selected (and Threaded)");
1065              /* now add the specific stuff for this button */
1066            }
1067            /* action performed */
1068          });
1069        break;
1070
1071      case 4:
1072        /* print preview */
1073        menuItem.addActionListener(
1074          new ActionListener()
1075          {
1076            /**
1077             *  Description of the Method
1078             *
1079             * @param  event  Description of Parameter
1080             */
1081            public void actionPerformed(ActionEvent event) {
1082              repaintMenuBar();
1083              debugOutput(3, " PRINT Preview MenuItem Selected");
1084              /* now add the specific stuff for this button */
1085            }
1086            /* action performed */
1087          });
1088        break;
1089
1090      case 6:
1091        /* close */
1092        menuItem.addActionListener(
1093          new ActionListener()
1094          {
1095            /**
1096             *  Description of the Method
1097             *
1098             * @param  event  Description of Parameter
1099             */
1100            public void actionPerformed(ActionEvent event) {
1101              repaintMenuBar();
1102              debugOutput(3, " Close MenuItem Selected");
1103              /* now add the specific stuff for this button */
1104            }
1105            /* action performed */
1106          });
1107        break;
1108
1109      case 7:
1110        /* exit */
1111        menuItem.addActionListener(
1112          new ActionListener()
1113          {
1114            /**
1115             *  Description of the Method
1116             *
1117             * @param  event  Description of Parameter
1118             */
1119            public void actionPerformed(ActionEvent event) {
1120              repaintMenuBar();
1121              debugOutput(3, " Exit MenuItem Pressed "  );
1122              /* now add the specific stuff for this button */
1123             stop();
1124             System.exit(0);
1125            }
1126            /* action performed */
1127          });
1128        break;
1129
1130      case 10:
1131        /* Set The Debug Level */
1132        menuItem.addActionListener(
1133          new ActionListener()
1134          {
1135            /**
1136             *  Description of the Method
1137             *
1138             * @param  event  Description of Parameter
1139             */
1140            public void actionPerformed(ActionEvent event) {
1141              repaintMenuBar();
1142              debugOutput(2, " Debug Level MenuItem Selected");
1143              /* now add the specific stuff for this button */
1144            }
1145            /* action performed */
1146          });
1147        break;
1148
1149      case 12:
1150        /* Set the L&F to Java */
1151        menuItem.addActionListener(
1152          new ActionListener()
1153          {
1154            /**
1155             *  Description of the Method
1156             *
1157             * @param  event  Description of Parameter
1158             */
1159            public void actionPerformed(ActionEvent event) {
1160              debugOutput(2, " Java L&F MenuItem Selected");
1161              repaintMenuBar();
1162
1163              /* now add the specific stuff for this button */
1164              setTheLookAndFeel(METAL_LOOKANDFEEL);
1165            }
1166            /* action performed */
1167          });
1168        break;
1169
1170      case 13:
1171        /* Set the L&F to Platform */
1172        menuItem.addActionListener(
1173          new ActionListener()
1174          {
1175            /**
1176             *  Description of the Method
1177             *
1178             * @param  event  Description of Parameter
1179             */
1180            public void actionPerformed(ActionEvent event) {
1181              repaintMenuBar();
1182              debugOutput(2, " Platform L&F MenuItem Selected");
1183              /* now add the specific stuff for this button */
1184              setTheLookAndFeel(WINDOZE_LOOKANDFEEL);
1185            }
1186            /* action performed */
1187          });
1188        break;
1189
1190      case 14:
1191        /* Set the L&F to Motif */
1192        menuItem.addActionListener(
1193          new ActionListener()
1194          {
1195            /**
1196             *  Description of the Method
1197             *
1198             * @param  event  Description of Parameter
1199             */
1200            public void actionPerformed(ActionEvent event) {
1201              repaintMenuBar();
1202              debugOutput(2, " Motif L&F MenuItem Selected");
1203              /* now add the specific stuff for this button */
1204              setTheLookAndFeel(MOTIF_LOOKANDFEEL);
1205            }
1206            /* action performed */
1207          });
1208        break;
1209
1210        case 18:
1211        /* Open the Help window */
1212        menuItem.addActionListener(
1213          new ActionListener()
1214          {
1215            /**
1216             *  Description of the Method
1217             *
1218             * @param  event  Description of Parameter
1219             */
1220            public void actionPerformed(ActionEvent event) {
1221              repaintMenuBar();
1222              debugOutput(2, " Help MenuItem Selected");
1223              /* now add the specific stuff for this button */
1224            }
1225            /* action performed */
1226          });
1227        break;
1228
1229      case 20:
1230        /* Open the About Box */
1231        menuItem.addActionListener(
1232          new ActionListener()
1233          {
1234            /**
1235             *  Description of the Method
1236             *
1237             * @param  event  Description of Parameter
1238             */
1239            public void actionPerformed(ActionEvent event) {
1240              repaintMenuBar();
1241              debugOutput(2, " About Box MenuItem Selected");
1242              /* now add the specific stuff for this button */
1243              JAboutBox box = new JAboutBox("Generic MDIApplet",getAppletInfo());
1244              box.show();
1245              box.toFront();
1246            }
1247            /* action performed */
1248          });
1249        break;
1250
1251      default:
1252         debugOutput(3, "??? menu item number"+
1253                     indexOf(menuItem.getToolTipText()));
1254//                                              repaintMenuBar();
1255    }
1256    /* switch for menuitem */
1257  }
1258
1259
1260  /**
1261   *  The main entry for running the MDIApplet as an APP.
1262   *
1263   * @param  args  The command line arguments
1264   */
1265  public static void main(String[] args) {
1266    isRunningAsAnApplet = false;
1267
1268    /*  Put the opening splash screen up   */
1269    debugOutput(2," ");
1270    debugOutput(2,"Splash Logo");
1271    Panel p = new Panel();
1272    p.setBackground(new Color(210,210,210));
1273    Label l = new Label("  Please wait while loading...");
1274    p.add(l);
1275    Splash frame = new Splash(splashGraphic, 5000,p);
1276
1277    /*  Get the current directory */
1278    userDir = System.getProperty("user.dir");
1279    debugOutput(3,"userdir=" + userDir);
1280
1281    /*  Get Current Time */
1282    currentDate = new java.util.Date();
1283
1284    /* create an app frame that will start this applet inside it */
1285    MyMDIApp app = new MyMDIApp("Generic MDI Desktop Template - WebARTS Design");
1286    app.setSize(800, 600);
1287
1288    /* Put the opening app up */
1289    app.show();
1290  }
1291
1292
1293  /**
1294   *  Handles debug messages by comparing the app debug level to the
1295   *  message level. If the message level is less or == then the
1296   *  message gets outout to System.out.
1297   *
1298   * @param  l       Description of Parameter
1299   * @param  output  Description of Parameter
1300   */
1301  private static void debugOutput(int l, String output) {
1302    if (l <= debug) System.out.println(output);
1303  }
1304
1305
1306
1307/**
1308 *  This is <B>the</B> object that will act as the main child window manager.
1309 *
1310 * @author     gutwint
1311 * @created    November 17, 2000
1312 */
1313class DesktopController extends  JDesktopPane
1314{
1315  /**
1316   * generic counter
1317   */
1318  private int i;
1319
1320  /**
1321   *  The pop up menu for this area
1322   */
1323  private JPopupMenu popupMenu;
1324
1325/**
1326 * MAX_CHILDREN is the constant representing the maximum number of children
1327 * that this class will allow in its desktop. It gets used to initialize
1328 * arrays and for general happiness. :)
1329 */
1330    static final private short   MAX_CHILDREN = 10;
1331
1332    /**an array of the files/internalwindows that can be used **/
1333  private JInternalFrame[] childWindow = new JInternalFrame[MAX_CHILDREN];
1334
1335/**
1336 * Reference number for the next child window to be created.
1337 */
1338  private short   nextWindowIndex = 0;
1339
1340/**
1341 * Reference number for the currently active child window.
1342 */
1343  private short   currentWindowIndex = nextWindowIndex;
1344
1345/**
1346 * The X coordinate for the next window.
1347 */
1348  private short   nextWindowXPos = 0;
1349
1350/**
1351 * The Y coordinate for the next window.
1352 */
1353  private short  nextWindowYPos = 110;
1354
1355//  private JScrollPane scroller = new JScrollPane();
1356  // set up a pop up menu when the mouse is over the pictures
1357
1358  /**
1359   *  Constructor for the desktopController object
1360   *
1361   * @param  codeBase  Description of Parameter
1362   */
1363  public DesktopController(URL codeBase)
1364  {
1365    super();
1366    System.out.println("Creating the desktopController....");
1367
1368    /* set up the popup menu */
1369    popupMenu = new JPopupMenu();
1370    popupMenu.add(new JMenuItem("New"));
1371    popupMenu.addSeparator();
1372    popupMenu.add(new JMenuItem("Close"));
1373    popupMenu.add(new JMenuItem("Exit"));
1374    enableEvents(AWTEvent.MOUSE_EVENT_MASK);
1375
1376 //   scroller.getViewport().setMinimumSize(new java.awt.Dimension(20, 15));
1377
1378    /* fill the arrays with the pictures and labels */
1379
1380    System.out.println("Done Creating a desktopController....");
1381  }
1382
1383
1384/**
1385 * Creates a new Internal Child Window that goes into this
1386 * Internal Desktop Pane/Panel.
1387 *
1388 * @return boolean Flags if the new window was created OKay.
1389 */
1390  public boolean makeNewChildWindow()
1391  {
1392    boolean retVal = false;
1393    JInternalFrame child;
1394    System.out.println(" Creating The NEW Child window....");
1395
1396
1397    /* create the new frame */
1398    child =  new JInternalFrame("Title",true,true,true,true);
1399
1400    if (child != null)
1401    {
1402      retVal = true;
1403      /* increase the index counters */
1404      currentWindowIndex = nextWindowIndex++;
1405      System.out.println(" ......Done calling Create for The NEW Child window...." +
1406                        currentWindowIndex);
1407
1408      childWindow[currentWindowIndex] = child;
1409      childWindow[currentWindowIndex].pack();
1410      childWindow[currentWindowIndex].setVisible(true) ;
1411
1412      /* add it to my desktop */
1413      add(childWindow[currentWindowIndex], JLayeredPane.PALETTE_LAYER);
1414      childWindow[currentWindowIndex].setLocation(nextWindowXPos,nextWindowYPos);
1415//      setContentPane(desktop);
1416      nextWindowXPos += 20;
1417      nextWindowYPos += 29;
1418
1419      try
1420      {
1421        childWindow[currentWindowIndex].moveToFront() ;
1422        childWindow[currentWindowIndex].setSelected(true);
1423      }
1424      catch (java.beans.PropertyVetoException ex)
1425        {
1426          System.out.println("EXCEPTION CAUGHT for:");
1427          System.out.println("                     " + ex.getMessage());
1428          System.out.println("Vetoed Property Change:");
1429          System.out.println("                     " + ex.getPropertyChangeEvent().getPropertyName());
1430      }
1431
1432      revalidate();
1433    }
1434    else
1435      System.out.println(" ......Done calling Create for The NEW Child window NO CONTENT");
1436
1437    return retVal;
1438  }
1439
1440  public int getCurrentWindowIndex()
1441  {
1442    return currentWindowIndex;
1443  }
1444
1445
1446  public int getNextWindowIndex()
1447  {
1448    return nextWindowIndex;
1449  }
1450
1451  public void addWindowContent(Component content)
1452  {
1453    JComponent c = (JComponent) childWindow[currentWindowIndex].getContentPane();
1454    c.setLayout(new BorderLayout());
1455    c.add(content);
1456    childWindow[currentWindowIndex].pack();
1457  }
1458
1459  public void addWindowContent(int windowIndex, Component content)
1460  {
1461    currentWindowIndex = (short) windowIndex;
1462    addWindowContent(content);
1463  }
1464
1465  /**
1466   *  Description of the Method
1467   *
1468   * @param  e  Description of Parameter
1469   */
1470  protected void processMouseEvent(MouseEvent e) {
1471    //          System.out.println("mouse event...." e.getID());
1472//              System.out.println();
1473//              System.out.println(e);
1474    if (e.isPopupTrigger())
1475    {
1476     // popupMenu.show(e.getComponent(), e.getX(), e.getY());
1477    }
1478    super.processMouseEvent(e);
1479  }
1480
1481}
1482
1483} //end of the MDIApplet JApplet
1484
1485
1486/**
1487 *  The App that holds the generic MDI  applet.
1488 *  It is simply a JFrame that encapsulates the applet as an application.
1489 *
1490 * @author     gutwint
1491 * @created    November 17, 2000
1492 */
1493class MyMDIApp extends JFrame
1494{
1495
1496
1497  /**
1498   *  Description of the Field
1499   */
1500  private MDIApplet myMDIApplet;
1501
1502
1503  /**
1504   *  Constructor.
1505   *
1506   * @param  frameTitle  Description of Parameter
1507   */
1508  public MyMDIApp(String frameTitle) {
1509    /* get the super class frame to build a frame with a title */
1510    super(frameTitle);
1511
1512    /* Instantiate the MediaViewer APPLET */
1513    myMDIApplet = new MDIApplet();
1514
1515    /* place it into the app frame */
1516    getContentPane().add(myMDIApplet, "Center");
1517
1518    /* Init the applet */
1519    myMDIApplet.init();
1520
1521    /* Start the applet */
1522    myMDIApplet.start();
1523
1524    /* listen for closing */
1525    addWindowListener(
1526      new WindowAdapter()
1527      {
1528        /**
1529         *  Description of the Method
1530         *
1531         * @param  event  Description of Parameter
1532         */
1533        public void windowClosing(WindowEvent event) {
1534          /* Start the applet */
1535          myMDIApplet.stop();
1536          dispose();
1537          System.exit(0);
1538        }
1539      });
1540    /* inner WindowAdapter class */
1541
1542  }
1543}