SwingSet2.java  
1   /*
2    * @(#)SwingSet2.java   1.50 04/07/26
3    * 
4    * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
5    * 
6    * Redistribution and use in source and binary forms, with or without
7    * modification, are permitted provided that the following conditions are met:
8    * 
9    * -Redistribution of source code must retain the above copyright notice, this
10   *  list of conditions and the following disclaimer.
11   * 
12   * -Redistribution in binary form must reproduce the above copyright notice, 
13   *  this list of conditions and the following disclaimer in the documentation
14   *  and/or other materials provided with the distribution.
15   * 
16   * Neither the name of Sun Microsystems, Inc. or the names of contributors may 
17   * be used to endorse or promote products derived from this software without 
18   * specific prior written permission.
19   * 
20   * This software is provided "AS IS," without a warranty of any kind. ALL 
21   * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22   * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23   * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
24   * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25   * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26   * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST 
27   * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, 
28   * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY 
29   * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 
30   * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31   * 
32   * You acknowledge that this software is not designed, licensed or intended
33   * for use in the design, construction, operation or maintenance of any
34   * nuclear facility.
35   */
36  
37  /*
38   * @(#)SwingSet2.java   1.50 04/07/26
39   */
40  
41  import javax.swing.*;
42  import javax.swing.event.*;
43  import javax.swing.text.*;
44  import javax.swing.border.*;
45  import javax.swing.colorchooser.*;
46  import javax.swing.filechooser.*;
47  import javax.accessibility.*;
48  
49  import javax.swing.plaf.metal.MetalTheme;
50  import javax.swing.plaf.metal.OceanTheme;
51  import javax.swing.plaf.metal.DefaultMetalTheme;
52  import javax.swing.plaf.metal.MetalLookAndFeel;
53  
54  import java.lang.reflect.*;
55  import java.awt.*;
56  import java.awt.event.*;
57  import java.beans.*;
58  import java.util.*;
59  import java.io.*;
60  import java.applet.*;
61  import java.net.*;
62  
63  /**
64   * A demo that shows all of the Swing components.
65   *
66   * @version 1.50 07/26/04
67   * @author Jeff Dinkins
68   */
69  public class SwingSet2 extends JPanel {
70  
71      String[] demos = {
72        "ButtonDemo",
73        "ColorChooserDemo",
74        "ComboBoxDemo",
75        "FileChooserDemo",
76        "HtmlDemo",
77        "ListDemo",
78        "OptionPaneDemo",
79        "ProgressBarDemo",
80        "ScrollPaneDemo",
81        "SliderDemo",
82        "SplitPaneDemo",
83        "TabbedPaneDemo",
84        "TableDemo",
85        "ToolTipDemo",
86        "TreeDemo"
87      };
88  
89      void loadDemos() {
90      for(int i = 0; i < demos.length;) {
91              if(isApplet() && demos[i].equals("FileChooserDemo")) {
92             // don't load the file chooser demo if we are
93                 // an applet
94          } else {
95             loadDemo(demos[i]);
96              }
97          i++;
98      }
99      }
100 
101     // Possible Look & Feels
102     private static final String mac      =
103             "com.sun.java.swing.plaf.mac.MacLookAndFeel";
104     private static final String metal    =
105             "javax.swing.plaf.metal.MetalLookAndFeel";
106     private static final String motif    =
107             "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
108     private static final String windows  =
109             "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
110     private static final String gtk  =
111             "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
112 
113     // The current Look & Feel
114     private static String currentLookAndFeel = metal;
115 
116     // List of demos
117     private ArrayList<DemoModule> demosList = new ArrayList<DemoModule>();
118 
119     // The preferred size of the demo
120     private static final int PREFERRED_WIDTH = 720;
121     private static final int PREFERRED_HEIGHT = 640;
122     
123     // Box spacers
124     private Dimension HGAP = new Dimension(1,5);
125     private Dimension VGAP = new Dimension(5,1);
126 
127     // Resource bundle for internationalized and accessible text
128     private ResourceBundle bundle = null;
129 
130     // A place to hold on to the visible demo
131     private DemoModule currentDemo = null;
132     private JPanel demoPanel = null;
133 
134     // About Box
135     private JDialog aboutBox = null;
136 
137     // Status Bar
138     private JTextField statusField = null;
139 
140     // Tool Bar
141     private ToggleButtonToolBar toolbar = null;
142     private ButtonGroup toolbarGroup = new ButtonGroup();
143 
144     // Menus
145     private JMenuBar menuBar = null;
146     private JMenu lafMenu = null;
147     private JMenu themesMenu = null;
148     private JMenu audioMenu = null;
149     private JMenu optionsMenu = null;
150     private ButtonGroup lafMenuGroup = new ButtonGroup();
151     private ButtonGroup themesMenuGroup = new ButtonGroup();
152     private ButtonGroup audioMenuGroup = new ButtonGroup();
153 
154     // Popup menu
155     private JPopupMenu popupMenu = null;
156     private ButtonGroup popupMenuGroup = new ButtonGroup();
157 
158     // Used only if swingset is an application 
159     private JFrame frame = null;
160     private JWindow splashScreen = null;
161 
162     // Used only if swingset is an applet 
163     private SwingSet2Applet applet = null;
164 
165     // To debug or not to debug, that is the question
166     private boolean DEBUG = true;
167     private int debugCounter = 0;
168 
169     // The tab pane that holds the demo
170     private JTabbedPane tabbedPane = null;
171 
172     private JEditorPane demoSrcPane = null;
173 
174     private JLabel splashLabel = null;
175 
176     // contentPane cache, saved from the applet or application frame
177     Container contentPane = null;
178 
179 
180     // number of swingsets - for multiscreen
181     // keep track of the number of SwingSets created - we only want to exit
182     // the program when the last one has been closed.
183     private static int numSSs = 0;
184     private static Vector<SwingSet2> swingSets = new Vector<SwingSet2>();
185     
186     private boolean dragEnabled = false;
187 
188     public SwingSet2(SwingSet2Applet applet) {
189         this(applet, null);
190     }
191 
192     /**
193      * SwingSet2 Constructor
194      */
195     public SwingSet2(SwingSet2Applet applet, GraphicsConfiguration gc) {
196 
197     // Note that the applet may null if this is started as an application
198     this.applet = applet;
199 
200     // Create Frame here for app-mode so the splash screen can get the
201     // GraphicsConfiguration from it in createSplashScreen()
202     if (!isApplet()) {
203         frame = createFrame(gc);
204     }
205 
206     // setLayout(new BorderLayout());
207     setLayout(new BorderLayout());
208 
209     // set the preferred size of the demo
210     setPreferredSize(new Dimension(PREFERRED_WIDTH,PREFERRED_HEIGHT));
211 
212     // Create and throw the splash screen up. Since this will
213     // physically throw bits on the screen, we need to do this
214     // on the GUI thread using invokeLater.
215     createSplashScreen();
216 
217     // do the following on the gui thread
218     SwingUtilities.invokeLater(new Runnable() {
219         public void run() {
220         showSplashScreen();
221         }
222     });
223         
224     initializeDemo();
225     preloadFirstDemo();
226 
227     // Show the demo and take down the splash screen. Note that
228     // we again must do this on the GUI thread using invokeLater.
229     SwingUtilities.invokeLater(new Runnable() {
230         public void run() {
231         showSwingSet2();
232         hideSplash();
233         }
234     });
235 
236     // Start loading the rest of the demo in the background
237     DemoLoadThread demoLoader = new DemoLoadThread(this);
238     demoLoader.start();
239     }
240 
241 
242     /**
243      * SwingSet2 Main. Called only if we're an application, not an applet.
244      */
245     public static void main(String[] args) {
246     // Create SwingSet on the default monitor
247         UIManager.put("swing.boldMetal", Boolean.FALSE);
248     SwingSet2 swingset = new SwingSet2(null, GraphicsEnvironment.
249                                              getLocalGraphicsEnvironment().
250                                              getDefaultScreenDevice().
251                                              getDefaultConfiguration());
252     }
253 
254     // *******************************************************
255     // *************** Demo Loading Methods ******************
256     // *******************************************************
257     
258     
259     
260     public void initializeDemo() {
261     JPanel top = new JPanel();
262     top.setLayout(new BorderLayout());
263     add(top, BorderLayout.NORTH);
264 
265     menuBar = createMenus();
266     
267     if (isApplet()) {
268         applet.setJMenuBar(menuBar);
269     } else {
270         frame.setJMenuBar(menuBar);
271     }
272 
273     // creates popup menu accessible via keyboard
274     popupMenu = createPopupMenu();
275 
276     ToolBarPanel toolbarPanel = new ToolBarPanel();
277     toolbarPanel.setLayout(new BorderLayout());
278     toolbar = new ToggleButtonToolBar();
279     toolbarPanel.add(toolbar, BorderLayout.CENTER);
280     top.add(toolbarPanel, BorderLayout.SOUTH);
281     toolbarPanel.addContainerListener(toolbarPanel);
282 
283     tabbedPane = new JTabbedPane();
284     add(tabbedPane, BorderLayout.CENTER);
285     tabbedPane.getModel().addChangeListener(new TabListener());
286 
287     statusField = new JTextField("");
288     statusField.setEditable(false);
289     add(statusField, BorderLayout.SOUTH);
290     
291     demoPanel = new JPanel();
292     demoPanel.setLayout(new BorderLayout());
293     demoPanel.setBorder(new EtchedBorder());
294     tabbedPane.addTab("Hi There!", demoPanel);
295     
296     // Add html src code viewer 
297     demoSrcPane = new JEditorPane("text/html", getString("SourceCode.loading"));
298     demoSrcPane.setEditable(false);
299 
300     JScrollPane scroller = new JScrollPane();
301     scroller.getViewport().add(demoSrcPane);
302     
303     tabbedPane.addTab(
304         getString("TabbedPane.src_label"),
305         null,
306         scroller,
307         getString("TabbedPane.src_tooltip")
308     );
309     }
310 
311     DemoModule currentTabDemo = null;
312     class TabListener implements ChangeListener {
313     public void stateChanged(ChangeEvent e) {
314         SingleSelectionModel model = (SingleSelectionModel) e.getSource();
315         boolean srcSelected = model.getSelectedIndex() == 1;
316         if(currentTabDemo != currentDemo && demoSrcPane != null && srcSelected) {
317         demoSrcPane.setText(getString("SourceCode.loading"));
318         repaint();
319         }
320         if(currentTabDemo != currentDemo && srcSelected) {
321         currentTabDemo = currentDemo;
322         setSourceCode(currentDemo);
323         } 
324     }
325     }
326 
327 
328     /**
329      * Create menus
330      */
331     public JMenuBar createMenus() {
332     JMenuItem mi;
333     // ***** create the menubar ****
334     JMenuBar menuBar = new JMenuBar();
335     menuBar.getAccessibleContext().setAccessibleName(
336         getString("MenuBar.accessible_description"));
337 
338     // ***** create File menu 
339     JMenu fileMenu = (JMenu) menuBar.add(new JMenu(getString("FileMenu.file_label")));
340         fileMenu.setMnemonic(getMnemonic("FileMenu.file_mnemonic"));
341     fileMenu.getAccessibleContext().setAccessibleDescription(getString("FileMenu.accessible_description"));
342 
343     createMenuItem(fileMenu, "FileMenu.about_label", "FileMenu.about_mnemonic",
344                "FileMenu.about_accessible_description", new AboutAction(this));
345 
346         fileMenu.addSeparator();
347 
348     createMenuItem(fileMenu, "FileMenu.open_label", "FileMenu.open_mnemonic",
349                "FileMenu.open_accessible_description", null);
350 
351     createMenuItem(fileMenu, "FileMenu.save_label", "FileMenu.save_mnemonic",
352                "FileMenu.save_accessible_description", null);
353 
354     createMenuItem(fileMenu, "FileMenu.save_as_label", "FileMenu.save_as_mnemonic",
355                "FileMenu.save_as_accessible_description", null);
356 
357 
358     if(!isApplet()) {
359         fileMenu.addSeparator();
360         
361         createMenuItem(fileMenu, "FileMenu.exit_label", "FileMenu.exit_mnemonic",
362                "FileMenu.exit_accessible_description", new ExitAction(this)
363         );
364     }
365 
366         // Create these menu items for the first SwingSet only.
367         if (numSSs == 0) {
368     // ***** create laf switcher menu 
369     lafMenu = (JMenu) menuBar.add(new JMenu(getString("LafMenu.laf_label")));
370         lafMenu.setMnemonic(getMnemonic("LafMenu.laf_mnemonic"));
371     lafMenu.getAccessibleContext().setAccessibleDescription(
372         getString("LafMenu.laf_accessible_description"));
373 
374     mi = createLafMenuItem(lafMenu, "LafMenu.java_label", "LafMenu.java_mnemonic",
375                "LafMenu.java_accessible_description", metal);
376     mi.setSelected(true); // this is the default l&f
377 
378         UIManager.LookAndFeelInfo[] lafInfo = UIManager.
379                                        getInstalledLookAndFeels();
380 
381         for (int counter = 0; counter < lafInfo.length; counter++) {
382             String className = lafInfo[counter].getClassName();
383             if (className == motif) {
384                 createLafMenuItem(lafMenu, "LafMenu.motif_label", "LafMenu.motif_mnemonic",
385                         "LafMenu.motif_accessible_description", motif);        
386             } else if (className == windows) {
387                 createLafMenuItem(lafMenu, "LafMenu.windows_label", "LafMenu.windows_mnemonic",
388                         "LafMenu.windows_accessible_description", windows);
389             } else if (className == gtk) {
390                 createLafMenuItem(lafMenu, "LafMenu.gtk_label", "LafMenu.gtk_mnemonic", 
391                         "LafMenu.gtk_accessible_description", gtk);
392             }
393         }
394 
395     // ***** create themes menu 
396     themesMenu = (JMenu) menuBar.add(new JMenu(getString("ThemesMenu.themes_label")));
397         themesMenu.setMnemonic(getMnemonic("ThemesMenu.themes_mnemonic"));
398     themesMenu.getAccessibleContext().setAccessibleDescription(
399         getString("ThemesMenu.themes_accessible_description"));
400 
401     // ***** create the audio submenu under the theme menu
402     audioMenu = (JMenu) themesMenu.add(new JMenu(getString("AudioMenu.audio_label")));
403         audioMenu.setMnemonic(getMnemonic("AudioMenu.audio_mnemonic"));
404     audioMenu.getAccessibleContext().setAccessibleDescription(
405         getString("AudioMenu.audio_accessible_description"));
406 
407     createAudioMenuItem(audioMenu, "AudioMenu.on_label",
408                 "AudioMenu.on_mnemonic", 
409                 "AudioMenu.on_accessible_description",
410                 new OnAudioAction(this));
411 
412     mi = createAudioMenuItem(audioMenu, "AudioMenu.default_label",
413                  "AudioMenu.default_mnemonic", 
414                  "AudioMenu.default_accessible_description",
415                  new DefaultAudioAction(this));
416     mi.setSelected(true); // This is the default feedback setting
417 
418     createAudioMenuItem(audioMenu, "AudioMenu.off_label",
419                 "AudioMenu.off_mnemonic", 
420                 "AudioMenu.off_accessible_description",
421                 new OffAudioAction(this));
422 
423 
424     // ***** create the font submenu under the theme menu
425     JMenu fontMenu = (JMenu) themesMenu.add(new JMenu(getString("FontMenu.fonts_label")));
426         fontMenu.setMnemonic(getMnemonic("FontMenu.fonts_mnemonic"));
427     fontMenu.getAccessibleContext().setAccessibleDescription(
428         getString("FontMenu.fonts_accessible_description"));
429         ButtonGroup fontButtonGroup = new ButtonGroup();
430         mi = createButtonGroupMenuItem(fontMenu, "FontMenu.plain_label",
431                 "FontMenu.plain_mnemonic",
432                 "FontMenu.plain_accessible_description",
433                 new ChangeFontAction(this, true), fontButtonGroup);
434         mi.setSelected(true);
435         mi = createButtonGroupMenuItem(fontMenu, "FontMenu.bold_label",
436                 "FontMenu.bold_mnemonic",
437                 "FontMenu.bold_accessible_description",
438                 new ChangeFontAction(this, false), fontButtonGroup);
439 
440 
441 
442     // *** now back to adding color/font themes to the theme menu
443         mi = createThemesMenuItem(themesMenu, "ThemesMenu.ocean_label",
444                                               "ThemesMenu.ocean_mnemonic",
445                                               "ThemesMenu.ocean_accessible_description",
446                                               new OceanTheme());
447         mi.setSelected(true); // This is the default theme
448 
449         createThemesMenuItem(themesMenu, "ThemesMenu.steel_label",
450                              "ThemesMenu.steel_mnemonic",
451                              "ThemesMenu.steel_accessible_description",
452                              new DefaultMetalTheme());
453     
454     createThemesMenuItem(themesMenu, "ThemesMenu.aqua_label", "ThemesMenu.aqua_mnemonic",
455                "ThemesMenu.aqua_accessible_description", new AquaTheme());
456 
457     createThemesMenuItem(themesMenu, "ThemesMenu.charcoal_label", "ThemesMenu.charcoal_mnemonic",
458                "ThemesMenu.charcoal_accessible_description", new CharcoalTheme());
459 
460     createThemesMenuItem(themesMenu, "ThemesMenu.contrast_label", "ThemesMenu.contrast_mnemonic",
461                "ThemesMenu.contrast_accessible_description", new ContrastTheme());
462 
463     createThemesMenuItem(themesMenu, "ThemesMenu.emerald_label", "ThemesMenu.emerald_mnemonic",
464                "ThemesMenu.emerald_accessible_description", new EmeraldTheme());
465 
466     createThemesMenuItem(themesMenu, "ThemesMenu.ruby_label", "ThemesMenu.ruby_mnemonic",
467                "ThemesMenu.ruby_accessible_description", new RubyTheme());
468 
469         // ***** create the options menu
470         optionsMenu = (JMenu)menuBar.add(
471             new JMenu(getString("OptionsMenu.options_label")));
472         optionsMenu.setMnemonic(getMnemonic("OptionsMenu.options_mnemonic"));
473         optionsMenu.getAccessibleContext().setAccessibleDescription(
474             getString("OptionsMenu.options_accessible_description"));
475 
476         // ***** create tool tip submenu item.
477         mi = createCheckBoxMenuItem(optionsMenu, "OptionsMenu.tooltip_label",
478                 "OptionsMenu.tooltip_mnemonic",
479                 "OptionsMenu.tooltip_accessible_description",
480                 new ToolTipAction());
481         mi.setSelected(true);
482 
483         // ***** create drag support submenu item.
484         createCheckBoxMenuItem(optionsMenu, "OptionsMenu.dragEnabled_label",
485                 "OptionsMenu.dragEnabled_mnemonic",
486                 "OptionsMenu.dragEnabled_accessible_description",
487                 new DragSupportAction());
488 
489         }
490 
491 
492     // ***** create the multiscreen menu, if we have multiple screens
493     if (!isApplet()) {
494         GraphicsDevice[] screens = GraphicsEnvironment.
495                                     getLocalGraphicsEnvironment().
496                                     getScreenDevices();
497         if (screens.length > 1) {
498 
499             JMenu multiScreenMenu = (JMenu) menuBar.add(new JMenu(
500                                      getString("MultiMenu.multi_label")));
501 
502             multiScreenMenu.setMnemonic(getMnemonic("MultiMenu.multi_mnemonic"));    
503             multiScreenMenu.getAccessibleContext().setAccessibleDescription(
504              getString("MultiMenu.multi_accessible_description"));
505 
506             createMultiscreenMenuItem(multiScreenMenu, MultiScreenAction.ALL_SCREENS);
507             for (int i = 0; i < screens.length; i++) {
508                 createMultiscreenMenuItem(multiScreenMenu, i);
509             }
510         }
511     }
512 
513     return menuBar;
514     }
515 
516     /**
517      * Create a checkbox menu menu item
518      */
519     private JMenuItem createCheckBoxMenuItem(JMenu menu, String label,
520                                              String mnemonic,
521                                              String accessibleDescription,
522                                              Action action) {
523         JCheckBoxMenuItem mi = (JCheckBoxMenuItem)menu.add(
524                 new JCheckBoxMenuItem(getString(label)));
525         mi.setMnemonic(getMnemonic(mnemonic));
526         mi.getAccessibleContext().setAccessibleDescription(getString(
527                 accessibleDescription));
528         mi.addActionListener(action);
529         return mi;
530     }
531 
532     /**
533      * Create a radio button menu menu item for items that are part of a
534      * button group.
535      */
536     private JMenuItem createButtonGroupMenuItem(JMenu menu, String label,
537                                                 String mnemonic,
538                                                 String accessibleDescription,
539                                                 Action action,
540                                                 ButtonGroup buttonGroup) {
541         JRadioButtonMenuItem mi = (JRadioButtonMenuItem)menu.add(
542                 new JRadioButtonMenuItem(getString(label)));
543         buttonGroup.add(mi);
544         mi.setMnemonic(getMnemonic(mnemonic));
545         mi.getAccessibleContext().setAccessibleDescription(getString(
546                 accessibleDescription));
547         mi.addActionListener(action);
548         return mi;
549     }
550 
551     /**
552      * Create the theme's audio submenu
553      */
554     public JMenuItem createAudioMenuItem(JMenu menu, String label,
555                      String mnemonic,
556                      String accessibleDescription,
557                      Action action) {
558         JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));
559     audioMenuGroup.add(mi);
560     mi.setMnemonic(getMnemonic(mnemonic));
561     mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
562     mi.addActionListener(action);
563 
564     return mi;
565     }
566 
567     /**
568      * Creates a generic menu item
569      */
570     public JMenuItem createMenuItem(JMenu menu, String label, String mnemonic,
571                    String accessibleDescription, Action action) {
572         JMenuItem mi = (JMenuItem) menu.add(new JMenuItem(getString(label)));
573     mi.setMnemonic(getMnemonic(mnemonic));
574     mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
575     mi.addActionListener(action);
576     if(action == null) {
577         mi.setEnabled(false);
578     }
579     return mi;
580     }
581 
582     /**
583      * Creates a JRadioButtonMenuItem for the Themes menu
584      */
585     public JMenuItem createThemesMenuItem(JMenu menu, String label, String mnemonic,
586                    String accessibleDescription, MetalTheme theme) {
587         JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));
588     themesMenuGroup.add(mi);
589     mi.setMnemonic(getMnemonic(mnemonic));
590     mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
591     mi.addActionListener(new ChangeThemeAction(this, theme));
592 
593     return mi;
594     }
595 
596     /**
597      * Creates a JRadioButtonMenuItem for the Look and Feel menu
598      */
599     public JMenuItem createLafMenuItem(JMenu menu, String label, String mnemonic,
600                    String accessibleDescription, String laf) {
601         JMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));
602     lafMenuGroup.add(mi);
603     mi.setMnemonic(getMnemonic(mnemonic));
604     mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
605     mi.addActionListener(new ChangeLookAndFeelAction(this, laf));
606 
607     mi.setEnabled(isAvailableLookAndFeel(laf));
608 
609     return mi;
610     }
611 
612     /**
613      * Creates a multi-screen menu item
614      */
615     public JMenuItem createMultiscreenMenuItem(JMenu menu, int screen) {
616         JMenuItem mi = null;
617         if (screen == MultiScreenAction.ALL_SCREENS) {
618             mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.all_label")));
619             mi.setMnemonic(getMnemonic("MultiMenu.all_mnemonic"));
620             mi.getAccessibleContext().setAccessibleDescription(getString(
621                                                                  "MultiMenu.all_accessible_description"));
622         }
623         else {
624             mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.single_label") + " " +
625                                                                                                  screen));
626             mi.setMnemonic(KeyEvent.VK_0 + screen);
627             mi.getAccessibleContext().setAccessibleDescription(getString(
628                                                "MultiMenu.single_accessible_description") + " " + screen);
629                                                                                             
630         }
631         mi.addActionListener(new MultiScreenAction(this, screen));
632         return mi;
633     }
634 
635     public JPopupMenu createPopupMenu() {
636     JPopupMenu popup = new JPopupMenu("JPopupMenu demo");
637     
638     createPopupMenuItem(popup, "LafMenu.java_label", "LafMenu.java_mnemonic",
639                 "LafMenu.java_accessible_description", metal);
640     
641     createPopupMenuItem(popup, "LafMenu.mac_label", "LafMenu.mac_mnemonic",
642                 "LafMenu.mac_accessible_description", mac);
643     
644     createPopupMenuItem(popup, "LafMenu.motif_label", "LafMenu.motif_mnemonic",
645                 "LafMenu.motif_accessible_description", motif);
646     
647     createPopupMenuItem(popup, "LafMenu.windows_label", "LafMenu.windows_mnemonic",
648                 "LafMenu.windows_accessible_description", windows);
649     
650     createPopupMenuItem(popup, "LafMenu.gtk_label", "LafMenu.gtk_mnemonic",
651                 "LafMenu.gtk_accessible_description", gtk);
652 
653     // register key binding to activate popup menu
654     InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
655     map.put(KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.SHIFT_MASK),
656         "postMenuAction");
657     getActionMap().put("postMenuAction", new ActivatePopupMenuAction(this, popup));
658     
659     return popup;
660     }
661     
662     /**
663      * Creates a JMenuItem for the Look and Feel popup menu
664      */
665     public JMenuItem createPopupMenuItem(JPopupMenu menu, String label, String mnemonic,
666                      String accessibleDescription, String laf) {
667     JMenuItem mi = menu.add(new JMenuItem(getString(label)));
668     popupMenuGroup.add(mi);
669     mi.setMnemonic(getMnemonic(mnemonic));
670     mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
671     mi.addActionListener(new ChangeLookAndFeelAction(this, laf));
672     mi.setEnabled(isAvailableLookAndFeel(laf));
673     
674     return mi;
675     }
676     
677 
678     /**
679      * Load the first demo. This is done separately from the remaining demos
680      * so that we can get SwingSet2 up and available to the user quickly.
681      */
682     public void preloadFirstDemo() {
683     DemoModule demo = addDemo(new InternalFrameDemo(this));
684     setDemo(demo);
685     }
686 
687 
688     /**
689      * Add a demo to the toolbar
690      */
691     public DemoModule addDemo(DemoModule demo) {
692     demosList.add(demo);
693         if (dragEnabled) {
694             demo.updateDragEnabled(true);
695         }
696     // do the following on the gui thread
697     SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {
698         public void run() {
699         SwitchToDemoAction action = new SwitchToDemoAction(swingset, (DemoModule) obj);
700         JToggleButton tb = swingset.getToolBar().addToggleButton(action);
701         swingset.getToolBarGroup().add(tb);
702         if(swingset.getToolBarGroup().getSelection() == null) {
703             tb.setSelected(true);
704         }
705         tb.setText(null);
706         tb.setToolTipText(((DemoModule)obj).getToolTip());
707 
708         if(demos[demos.length-1].equals(obj.getClass().getName())) {
709             setStatus(getString("Status.popupMenuAccessible"));
710         } 
711           
712         }
713     });
714     return demo;
715     }
716 
717 
718     /**
719      * Sets the current demo
720      */
721     public void setDemo(DemoModule demo) {
722     currentDemo = demo;
723 
724     // Ensure panel's UI is current before making visible
725     JComponent currentDemoPanel = demo.getDemoPanel();
726     SwingUtilities.updateComponentTreeUI(currentDemoPanel);
727 
728     demoPanel.removeAll();
729     demoPanel.add(currentDemoPanel, BorderLayout.CENTER);
730 
731     tabbedPane.setSelectedIndex(0);
732     tabbedPane.setTitleAt(0, demo.getName());
733     tabbedPane.setToolTipTextAt(0, demo.getToolTip());
734     }
735 
736 
737     /**
738      * Bring up the SwingSet2 demo by showing the frame (only
739      * applicable if coming up as an application, not an applet);
740      */
741     public void showSwingSet2() {
742     if(!isApplet() && getFrame() != null) {
743         // put swingset in a frame and show it
744         JFrame f = getFrame();
745         f.setTitle(getString("Frame.title"));
746         f.getContentPane().add(this, BorderLayout.CENTER);
747         f.pack();
748 
749         Rectangle screenRect = f.getGraphicsConfiguration().getBounds();
750             Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(
751                     f.getGraphicsConfiguration());
752 
753             // Make sure we don't place the demo off the screen.
754             int centerWidth = screenRect.width < f.getSize().width ?
755                     screenRect.x :
756                     screenRect.x + screenRect.width/2 - f.getSize().width/2;
757             int centerHeight = screenRect.height < f.getSize().height ?
758                     screenRect.y :
759                     screenRect.y + screenRect.height/2 - f.getSize().height/2;
760 
761             centerHeight = centerHeight < screenInsets.top ?
762                     screenInsets.top : centerHeight;
763 
764             f.setLocation(centerWidth, centerHeight);
765         f.show();
766             numSSs++;
767             swingSets.add(this);
768     } 
769     }
770 
771     /**
772      * Show the spash screen while the rest of the demo loads
773      */
774     public void createSplashScreen() {
775     splashLabel = new JLabel(createImageIcon("Splash.jpg", "Splash.accessible_description"));
776     
777     if(!isApplet()) {
778         splashScreen = new JWindow(getFrame());
779         splashScreen.getContentPane().add(splashLabel);
780         splashScreen.pack();
781         Rectangle screenRect = getFrame().getGraphicsConfiguration().getBounds();
782         splashScreen.setLocation(
783          screenRect.x + screenRect.width/2 - splashScreen.getSize().width/2,
784          screenRect.y + screenRect.height/2 - splashScreen.getSize().height/2);
785     } 
786     }
787 
788     public void showSplashScreen() {
789     if(!isApplet()) {
790         splashScreen.show();
791     } else {
792         add(splashLabel, BorderLayout.CENTER);
793         validate();
794         repaint();
795     }
796     }
797 
798     /**
799      * pop down the spash screen
800      */
801     public void hideSplash() {
802     if(!isApplet()) {
803         splashScreen.setVisible(false);
804         splashScreen = null;
805         splashLabel = null;
806     }
807     }
808 
809     // *******************************************************
810     // ****************** Utility Methods ********************
811     // *******************************************************
812 
813     /**
814      * Loads a demo from a classname
815      */
816     void loadDemo(String classname) {
817     setStatus(getString("Status.loading") + getString(classname + ".name"));
818     DemoModule demo = null;
819     try {
820         Class demoClass = Class.forName(classname);
821         Constructor demoConstructor = demoClass.getConstructor(new Class[]{SwingSet2.class});
822         demo = (DemoModule) demoConstructor.newInstance(new Object[]{this});
823         addDemo(demo);
824     } catch (Exception e) {
825         System.out.println("Error occurred loading demo: " + classname);
826     }
827     }
828     
829     /**
830      * A utility function that layers on top of the LookAndFeel's
831      * isSupportedLookAndFeel() method. Returns true if the LookAndFeel
832      * is supported. Returns false if the LookAndFeel is not supported
833      * and/or if there is any kind of error checking if the LookAndFeel
834      * is supported.
835      *
836      * The L&F menu will use this method to detemine whether the various
837      * L&F options should be active or inactive.
838      *
839      */
840      protected boolean isAvailableLookAndFeel(String laf) {
841          try { 
842              Class lnfClass = Class.forName(laf);
843              LookAndFeel newLAF = (LookAndFeel)(lnfClass.newInstance());
844              return newLAF.isSupportedLookAndFeel();
845          } catch(Exception e) { // If ANYTHING weird happens, return false
846              return false;
847          }
848      }
849 
850 
851     /**
852      * Determines if this is an applet or application
853      */
854     public boolean isApplet() {
855     return (applet != null);
856     }
857 
858     /**
859      * Returns the applet instance
860      */
861     public SwingSet2Applet getApplet() {
862     return applet;
863     }
864 
865 
866     /**
867      * Returns the frame instance
868      */
869     public JFrame getFrame() {
870     return frame;
871     }
872 
873     /**
874      * Returns the menubar
875      */
876     public JMenuBar getMenuBar() {
877     return menuBar;
878     }
879 
880     /**
881      * Returns the toolbar
882      */
883     public ToggleButtonToolBar getToolBar() {
884     return toolbar;
885     }
886 
887     /**
888      * Returns the toolbar button group
889      */
890     public ButtonGroup getToolBarGroup() {
891     return toolbarGroup;
892     }
893 
894     /**
895      * Returns the content pane wether we're in an applet
896      * or application
897      */
898     public Container getContentPane() {
899     if(contentPane == null) {
900         if(getFrame() != null) {
901         contentPane = getFrame().getContentPane();
902         } else if (getApplet() != null) {
903         contentPane = getApplet().getContentPane();
904         }
905     }
906     return contentPane;
907     }
908 
909     /**
910      * Create a frame for SwingSet2 to reside in if brought up
911      * as an application.
912      */
913     public static JFrame createFrame(GraphicsConfiguration gc) {
914     JFrame frame = new JFrame(gc);
915         if (numSSs == 0) {
916             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
917         } else {
918         WindowListener l = new WindowAdapter() {
919             public void windowClosing(WindowEvent e) {
920                     numSSs--;
921                     swingSets.remove(this);
922             }
923         };
924         frame.addWindowListener(l);
925         }
926     return frame;
927     }
928 
929 
930     /**
931      * Set the status 
932      */
933     public void setStatus(String s) {
934     // do the following on the gui thread
935     SwingUtilities.invokeLater(new SwingSetRunnable(this, s) {
936         public void run() {
937         swingset.statusField.setText((String) obj);
938         }
939     });
940     }
941 
942 
943     /**
944      * This method returns a string from the demo's resource bundle.
945      */
946     public String getString(String key) {
947     String value = null;
948     try {
949         value = getResourceBundle().getString(key);
950     } catch (MissingResourceException e) {
951         System.out.println("java.util.MissingResourceException: Couldn't find value for: " + key);
952     }
953     if(value == null) {
954         value = "Could not find resource: " + key + "  ";
955     }
956     return value;
957     }
958 
959     void setDragEnabled(boolean dragEnabled) {
960         if (dragEnabled == this.dragEnabled) {
961             return;
962         }
963 
964         this.dragEnabled = dragEnabled;
965 
966         for (DemoModule dm : demosList) {
967             dm.updateDragEnabled(dragEnabled);
968         }
969 
970         demoSrcPane.setDragEnabled(dragEnabled);
971     }
972     
973     boolean isDragEnabled() {
974         return dragEnabled;
975     }
976 
977     /**
978      * Returns the resource bundle associated with this demo. Used
979      * to get accessable and internationalized strings.
980      */
981     public ResourceBundle getResourceBundle() {
982     if(bundle == null) {
983         bundle = ResourceBundle.getBundle("resources.swingset");
984     }
985     return bundle;
986     }
987 
988     /**
989      * Returns a mnemonic from the resource bundle. Typically used as
990      * keyboard shortcuts in menu items.
991      */
992     public char getMnemonic(String key) {
993     return (getString(key)).charAt(0);
994     }
995 
996     /**
997      * Creates an icon from an image contained in the "images" directory.
998      */
999     public ImageIcon createImageIcon(String filename, String description) {
1000    String path = "/resources/images/" + filename;
1001    return new ImageIcon(getClass().getResource(path)); 
1002    }
1003
1004    /**
1005     * If DEBUG is defined, prints debug information out to std ouput.
1006     */
1007    public void debug(String s) {
1008    if(DEBUG) {
1009        System.out.println((debugCounter++) + ": " + s);
1010    }
1011    }
1012
1013    /**
1014     * Stores the current L&F, and calls updateLookAndFeel, below
1015     */
1016    public void setLookAndFeel(String laf) {
1017    if(currentLookAndFeel != laf) {
1018        currentLookAndFeel = laf;
1019            /* The recommended way of synchronizing state between multiple
1020             * controls that represent the same command is to use Actions.
1021             * The code below is a workaround and will be replaced in future
1022             * version of SwingSet2 demo.
1023             */
1024            String lafName = null;
1025            if(laf == mac) lafName = getString("LafMenu.mac_label");
1026            if(laf == metal) lafName = getString("LafMenu.java_label");
1027            if(laf == motif) lafName = getString("LafMenu.motif_label");
1028            if(laf == windows) lafName = getString("LafMenu.windows_label");
1029            if(laf == gtk) lafName = getString("LafMenu.gtk_label");
1030        themesMenu.setEnabled(laf == metal);
1031        updateLookAndFeel();
1032            for(int i=0;i<lafMenu.getItemCount();i++) {
1033                JMenuItem item = lafMenu.getItem(i);
1034                if(item.getText() == lafName) {
1035                    item.setSelected(true);
1036                } else {
1037                    item.setSelected(false);
1038                }
1039            }
1040    }
1041    }
1042
1043    private void updateThisSwingSet() {
1044        if (isApplet()) {
1045            SwingUtilities.updateComponentTreeUI(getApplet());
1046        } else {
1047            JFrame frame = getFrame();
1048            if (frame == null) {
1049                SwingUtilities.updateComponentTreeUI(this);
1050            } else {
1051                SwingUtilities.updateComponentTreeUI(frame);
1052            }
1053        }
1054
1055        SwingUtilities.updateComponentTreeUI(popupMenu);
1056        if (aboutBox != null) {
1057            SwingUtilities.updateComponentTreeUI(aboutBox);
1058        }
1059    }
1060
1061    /**
1062     * Sets the current L&F on each demo module
1063     */
1064    public void updateLookAndFeel() {
1065    try {
1066        UIManager.setLookAndFeel(currentLookAndFeel);
1067            if (isApplet()) {
1068                updateThisSwingSet();
1069            } else {
1070                for (SwingSet2 ss : swingSets) {
1071                    ss.updateThisSwingSet();
1072                }
1073            }
1074    } catch (Exception ex) {
1075        System.out.println("Failed loading L&F: " + currentLookAndFeel);
1076        System.out.println(ex);
1077    }
1078    }
1079
1080    /**
1081     * Loads and puts the source code text into JEditorPane in the "Source Code" tab
1082     */
1083    public void setSourceCode(DemoModule demo) {
1084    // do the following on the gui thread
1085    SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {
1086        public void run() {
1087        swingset.demoSrcPane.setText(((DemoModule)obj).getSourceCode());
1088        swingset.demoSrcPane.setCaretPosition(0);
1089
1090        }
1091    });
1092    }
1093
1094    // *******************************************************
1095    // **************   ToggleButtonToolbar  *****************
1096    // *******************************************************
1097    static Insets zeroInsets = new Insets(1,1,1,1);
1098    protected class ToggleButtonToolBar extends JToolBar {
1099    public ToggleButtonToolBar() {
1100        super();
1101    }
1102
1103    JToggleButton addToggleButton(Action a) {
1104        JToggleButton tb = new JToggleButton(
1105        (String)a.getValue(Action.NAME),
1106        (Icon)a.getValue(Action.SMALL_ICON)
1107        );
1108        tb.setMargin(zeroInsets);
1109        tb.setText(null);
1110        tb.setEnabled(a.isEnabled());
1111        tb.setToolTipText((String)a.getValue(Action.SHORT_DESCRIPTION));
1112        tb.setAction(a);
1113        add(tb);
1114        return tb;
1115    }
1116    }
1117
1118    // *******************************************************
1119    // *********  ToolBar Panel / Docking Listener ***********
1120    // *******************************************************
1121    class ToolBarPanel extends JPanel implements ContainerListener {
1122
1123    public boolean contains(int x, int y) {
1124        Component c = getParent();
1125        if (c != null) {
1126        Rectangle r = c.getBounds();
1127        return (x >= 0) && (x < r.width) && (y >= 0) && (y < r.height);
1128        }
1129        else {
1130        return super.contains(x,y);
1131        }
1132    }
1133
1134    public void componentAdded(ContainerEvent e) {
1135        Container c = e.getContainer().getParent();
1136        if (c != null) {
1137        c.getParent().validate();
1138        c.getParent().repaint();        
1139        }
1140    }
1141
1142    public void componentRemoved(ContainerEvent e) {
1143        Container c = e.getContainer().getParent();
1144        if (c != null) {
1145        c.getParent().validate();
1146        c.getParent().repaint();
1147        }
1148    }
1149    }
1150
1151    // *******************************************************
1152    // ******************   Runnables  ***********************
1153    // *******************************************************
1154
1155    /**
1156     * Generic SwingSet2 runnable. This is intended to run on the
1157     * AWT gui event thread so as not to muck things up by doing
1158     * gui work off the gui thread. Accepts a SwingSet2 and an Object
1159     * as arguments, which gives subtypes of this class the two
1160     * "must haves" needed in most runnables for this demo.
1161     */
1162    class SwingSetRunnable implements Runnable {
1163    protected SwingSet2 swingset;
1164    protected Object obj;
1165    
1166    public SwingSetRunnable(SwingSet2 swingset, Object obj) {
1167        this.swingset = swingset;
1168        this.obj = obj;
1169    }
1170
1171    public void run() {
1172    }
1173    }
1174    
1175    
1176    // *******************************************************
1177    // ********************   Actions  ***********************
1178    // *******************************************************
1179    
1180    public class SwitchToDemoAction extends AbstractAction {
1181    SwingSet2 swingset;
1182    DemoModule demo;
1183    
1184    public SwitchToDemoAction(SwingSet2 swingset, DemoModule demo) {
1185        super(demo.getName(), demo.getIcon());
1186        this.swingset = swingset;
1187        this.demo = demo;
1188    }
1189
1190    public void actionPerformed(ActionEvent e) {
1191        swingset.setDemo(demo);
1192    }
1193    }
1194
1195    class OkAction extends AbstractAction {
1196    JDialog aboutBox;
1197
1198        protected OkAction(JDialog aboutBox) {
1199            super("OkAction");
1200        this.aboutBox = aboutBox;
1201        }
1202
1203        public void actionPerformed(ActionEvent e) {
1204        aboutBox.setVisible(false);
1205    }
1206    }
1207
1208    class ChangeLookAndFeelAction extends AbstractAction {
1209    SwingSet2 swingset;
1210    String laf;
1211        protected ChangeLookAndFeelAction(SwingSet2 swingset, String laf) {
1212            super("ChangeTheme");
1213        this.swingset = swingset;
1214        this.laf = laf;
1215        }
1216
1217        public void actionPerformed(ActionEvent e) {
1218        swingset.setLookAndFeel(laf);
1219    }
1220    }
1221
1222    class ActivatePopupMenuAction extends AbstractAction {
1223    SwingSet2 swingset;
1224    JPopupMenu popup;
1225    protected ActivatePopupMenuAction(SwingSet2 swingset, JPopupMenu popup) {
1226        super("ActivatePopupMenu");
1227        this.swingset = swingset;
1228        this.popup = popup;
1229    }
1230    
1231    public void actionPerformed(ActionEvent e) {
1232        Dimension invokerSize = getSize();
1233        Dimension popupSize = popup.getPreferredSize();
1234        popup.show(swingset, (invokerSize.width - popupSize.width) / 2,
1235               (invokerSize.height - popupSize.height) / 2);
1236    }
1237    }
1238
1239    // Turns on all possible auditory feedback
1240    class OnAudioAction extends AbstractAction {
1241    SwingSet2 swingset;
1242        protected OnAudioAction(SwingSet2 swingset) {
1243            super("Audio On");
1244        this.swingset = swingset;
1245        }
1246        public void actionPerformed(ActionEvent e) {
1247        UIManager.put("AuditoryCues.playList",
1248              UIManager.get("AuditoryCues.allAuditoryCues"));
1249        swingset.updateLookAndFeel();
1250    }
1251    }
1252
1253    // Turns on the default amount of auditory feedback
1254    class DefaultAudioAction extends AbstractAction {
1255    SwingSet2 swingset;
1256        protected DefaultAudioAction(SwingSet2 swingset) {
1257            super("Audio Default");
1258        this.swingset = swingset;
1259        }
1260        public void actionPerformed(ActionEvent e) {
1261        UIManager.put("AuditoryCues.playList",
1262              UIManager.get("AuditoryCues.defaultCueList"));
1263        swingset.updateLookAndFeel();
1264    }
1265    }
1266
1267    // Turns off all possible auditory feedback
1268    class OffAudioAction extends AbstractAction {
1269    SwingSet2 swingset;
1270        protected OffAudioAction(SwingSet2 swingset) {
1271            super("Audio Off");
1272        this.swingset = swingset;
1273        }
1274        public void actionPerformed(ActionEvent e) {
1275        UIManager.put("AuditoryCues.playList",
1276              UIManager.get("AuditoryCues.noAuditoryCues"));
1277        swingset.updateLookAndFeel();
1278    }
1279    }
1280
1281    // Turns on or off the tool tips for the demo.
1282    class ToolTipAction extends AbstractAction {
1283        protected ToolTipAction() {
1284            super("ToolTip Control");
1285        }
1286
1287        public void actionPerformed(ActionEvent e) {
1288            boolean status = ((JCheckBoxMenuItem)e.getSource()).isSelected();
1289            ToolTipManager.sharedInstance().setEnabled(status);
1290        }
1291    }
1292
1293    class DragSupportAction extends AbstractAction {
1294        protected DragSupportAction() {
1295            super("DragSupport Control");
1296        }
1297        
1298        public void actionPerformed(ActionEvent e) {
1299            boolean dragEnabled = ((JCheckBoxMenuItem)e.getSource()).isSelected();
1300            if (isApplet()) {
1301                setDragEnabled(dragEnabled);
1302            } else {
1303                for (SwingSet2 ss : swingSets) {
1304                    ss.setDragEnabled(dragEnabled);
1305                }
1306            }
1307        }
1308    }
1309
1310    class ChangeThemeAction extends AbstractAction {
1311    SwingSet2 swingset;
1312    MetalTheme theme;
1313        protected ChangeThemeAction(SwingSet2 swingset, MetalTheme theme) {
1314            super("ChangeTheme");
1315        this.swingset = swingset;
1316        this.theme = theme;
1317        }
1318
1319        public void actionPerformed(ActionEvent e) {
1320        MetalLookAndFeel.setCurrentTheme(theme);
1321        swingset.updateLookAndFeel();
1322    }
1323    }
1324
1325    class ExitAction extends AbstractAction {
1326    SwingSet2 swingset;
1327        protected ExitAction(SwingSet2 swingset) {
1328            super("ExitAction");
1329        this.swingset = swingset;
1330        }
1331
1332        public void actionPerformed(ActionEvent e) {
1333        System.exit(0);
1334        }
1335    }
1336
1337    class AboutAction extends AbstractAction {
1338    SwingSet2 swingset;
1339        protected AboutAction(SwingSet2 swingset) {
1340            super("AboutAction");
1341        this.swingset = swingset;
1342        }
1343    
1344        public void actionPerformed(ActionEvent e) {
1345        if(aboutBox == null) {
1346        // JPanel panel = new JPanel(new BorderLayout());
1347        JPanel panel = new AboutPanel(swingset);
1348        panel.setLayout(new BorderLayout());
1349
1350        aboutBox = new JDialog(swingset.getFrame(), getString("AboutBox.title"), false);
1351                aboutBox.setResizable(false);
1352        aboutBox.getContentPane().add(panel, BorderLayout.CENTER);
1353
1354        // JButton button = new JButton(getString("AboutBox.ok_button_text"));
1355        JPanel buttonpanel = new JPanel();
1356        buttonpanel.setOpaque(false);
1357        JButton button = (JButton) buttonpanel.add(
1358            new JButton(getString("AboutBox.ok_button_text"))
1359        );
1360        panel.add(buttonpanel, BorderLayout.SOUTH);
1361
1362        button.addActionListener(new OkAction(aboutBox));
1363        }
1364        aboutBox.pack();
1365        Point p = swingset.getLocationOnScreen();
1366        aboutBox.setLocation(p.x + 10, p.y +10);
1367        aboutBox.show();
1368    }
1369    }
1370
1371    class MultiScreenAction extends AbstractAction {
1372        static final int ALL_SCREENS = -1;
1373        int screen;
1374        protected MultiScreenAction(SwingSet2 swingset, int screen) {
1375            super("MultiScreenAction");
1376            this.screen = screen;
1377        }
1378
1379        public void actionPerformed(ActionEvent e) {
1380            GraphicsDevice[] gds = GraphicsEnvironment.
1381                                   getLocalGraphicsEnvironment().
1382                                   getScreenDevices();
1383            if (screen == ALL_SCREENS) {
1384                for (int i = 0; i < gds.length; i++) {
1385                    SwingSet2 swingset = new SwingSet2(null,
1386                                  gds[i].getDefaultConfiguration());
1387                    swingset.setDragEnabled(dragEnabled);
1388                }
1389            }
1390            else {
1391                SwingSet2 swingset = new SwingSet2(null,
1392                             gds[screen].getDefaultConfiguration());
1393                swingset.setDragEnabled(dragEnabled);
1394            }
1395        }
1396    }
1397
1398    // *******************************************************
1399    // **********************  Misc  *************************
1400    // *******************************************************
1401
1402    class DemoLoadThread extends Thread {
1403    SwingSet2 swingset;
1404    
1405    public DemoLoadThread(SwingSet2 swingset) {
1406        this.swingset = swingset;
1407    }
1408
1409    public void run() {
1410        swingset.loadDemos();
1411    }
1412    }
1413
1414    class AboutPanel extends JPanel {
1415    ImageIcon aboutimage = null;
1416    SwingSet2 swingset = null;
1417
1418    public AboutPanel(SwingSet2 swingset) {
1419        this.swingset = swingset;
1420        aboutimage = swingset.createImageIcon("About.jpg", "AboutBox.accessible_description");
1421        setOpaque(false);
1422    }
1423
1424    public void paint(Graphics g) {
1425        aboutimage.paintIcon(this, g, 0, 0);
1426        super.paint(g);
1427    }
1428
1429    public Dimension getPreferredSize() {
1430        return new Dimension(aboutimage.getIconWidth(),
1431                 aboutimage.getIconHeight());
1432    }
1433    }
1434
1435
1436    private class ChangeFontAction extends AbstractAction {
1437    private SwingSet2 swingset;
1438        private boolean plain;
1439
1440        ChangeFontAction(SwingSet2 swingset, boolean plain) {
1441            super("FontMenu");
1442        this.swingset = swingset;
1443            this.plain = plain;
1444        }
1445
1446        public void actionPerformed(ActionEvent e) {
1447            if (plain) {
1448                UIManager.put("swing.boldMetal", Boolean.FALSE);
1449            }
1450            else {
1451                UIManager.put("swing.boldMetal", Boolean.TRUE);
1452            }
1453            // Change the look and feel to force the settings to take effect.
1454            updateLookAndFeel();
1455        }
1456    }
1457}
1458
1459