/*
 *
 * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;

import javax.swing.plaf.metal.MetalTheme;
import javax.swing.plaf.metal.OceanTheme;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;

import java.lang.reflect.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

/**
 * A demo that shows all of the Swing components.
 *
 * @author Jeff Dinkins
 */
public class SwingSet2 extends JPanel {

    String[] demos = {
      "ButtonDemo",
      "ColorChooserDemo",
      "ComboBoxDemo",
      "FileChooserDemo",
      "HtmlDemo",
      "ListDemo",
      "OptionPaneDemo",
      "ProgressBarDemo",
      "ScrollPaneDemo",
      "SliderDemo",
      "SplitPaneDemo",
      "TabbedPaneDemo",
      "TableDemo",
      "ToolTipDemo",
      "TreeDemo"
    };

    void loadDemos() {
        for(int i = 0; i < demos.length;) {
            loadDemo(demos[i]);
            i++;
        }
    }

    // The current Look & Feel
    private static LookAndFeelData currentLookAndFeel;
    private static LookAndFeelData[] lookAndFeelData;
    // List of demos
    private ArrayList<DemoModule> demosList = new ArrayList<DemoModule>();

    // The preferred size of the demo
    private static final int PREFERRED_WIDTH = 720;
    private static final int PREFERRED_HEIGHT = 640;

    // Box spacers
    private Dimension HGAP = new Dimension(1,5);
    private Dimension VGAP = new Dimension(5,1);

    // A place to hold on to the visible demo
    private DemoModule currentDemo = null;
    private JPanel demoPanel = null;

    // About Box
    private JDialog aboutBox = null;

    // Status Bar
    private JTextField statusField = null;

    // Tool Bar
    private ToggleButtonToolBar toolbar = null;
    private ButtonGroup toolbarGroup = new ButtonGroup();

    // Menus
    private JMenuBar menuBar = null;
    private JMenu lafMenu = null;
    private JMenu themesMenu = null;
    private JMenu audioMenu = null;
    private JMenu optionsMenu = null;
    private ButtonGroup lafMenuGroup = new ButtonGroup();
    private ButtonGroup themesMenuGroup = new ButtonGroup();
    private ButtonGroup audioMenuGroup = new ButtonGroup();

    // Popup menu
    private JPopupMenu popupMenu = null;
    private ButtonGroup popupMenuGroup = new ButtonGroup();

    // Used only if swingset is an application
    private JFrame frame = null;

    // To debug or not to debug, that is the question
    private boolean DEBUG = true;
    private int debugCounter = 0;

    // The tab pane that holds the demo
    private JTabbedPane tabbedPane = null;

    private JEditorPane demoSrcPane = null;


    // contentPane cache, saved from the applet or application frame
    Container contentPane = null;


    // number of swingsets - for multiscreen
    // keep track of the number of SwingSets created - we only want to exit
    // the program when the last one has been closed.
    private static int numSSs = 0;
    private static Vector<SwingSet2> swingSets = new Vector<SwingSet2>();

    private boolean dragEnabled = false;

    public SwingSet2() {
        this(null);
    }

    /**
     * SwingSet2 Constructor
     */
    public SwingSet2(GraphicsConfiguration gc) {
        String lafClassName = UIManager.getLookAndFeel().getClass().getName();
        lookAndFeelData = getInstalledLookAndFeelData();
        currentLookAndFeel = Arrays.stream(lookAndFeelData)
                .filter(laf -> lafClassName.equals(laf.className))
                .findFirst().get();

        frame = createFrame(gc);

        // set the layout
        setLayout(new BorderLayout());

        // set the preferred size of the demo
        setPreferredSize(new Dimension(PREFERRED_WIDTH,PREFERRED_HEIGHT));

        initializeDemo();
        preloadFirstDemo();

        showSwingSet2();

        // Start loading the rest of the demo in the background
        DemoLoadThread demoLoader = new DemoLoadThread(this);
        demoLoader.start();
    }


    /**
     * SwingSet2 Main. Called only if we're an application, not an applet.
     */
    public static void main(final String[] args) {
        // must run in EDT when constructing the GUI components
        SwingUtilities.invokeLater(() -> {
            // Create SwingSet on the default monitor
            UIManager.put("swing.boldMetal", Boolean.FALSE);
            SwingSet2 swingset = new SwingSet2(GraphicsEnvironment.
                                         getLocalGraphicsEnvironment().
                                         getDefaultScreenDevice().
                                         getDefaultConfiguration());
        });
    }

    // *******************************************************
    // *************** Demo Loading Methods ******************
    // *******************************************************



    public void initializeDemo() {
        JPanel top = new JPanel();
        top.setLayout(new BorderLayout());
        add(top, BorderLayout.NORTH);

        menuBar = createMenus();

        frame.setJMenuBar(menuBar);

        // creates popup menu accessible via keyboard
        popupMenu = createPopupMenu();

        ToolBarPanel toolbarPanel = new ToolBarPanel();
        toolbarPanel.setLayout(new BorderLayout());
        toolbar = new ToggleButtonToolBar();
        toolbarPanel.add(toolbar, BorderLayout.CENTER);
        top.add(toolbarPanel, BorderLayout.SOUTH);
        toolbarPanel.addContainerListener(toolbarPanel);

        tabbedPane = new JTabbedPane();
        add(tabbedPane, BorderLayout.CENTER);
        tabbedPane.getModel().addChangeListener(new TabListener());

        statusField = new JTextField("");
        statusField.setEditable(false);
        add(statusField, BorderLayout.SOUTH);

        demoPanel = new JPanel();
        demoPanel.setLayout(new BorderLayout());
        demoPanel.setBorder(new EtchedBorder());
        tabbedPane.addTab("Hi There!", demoPanel);

        // Add html src code viewer
        demoSrcPane = new JEditorPane("text/html", getString("SourceCode.loading"));
        demoSrcPane.setEditable(false);

        JScrollPane scroller = new JScrollPane();
        scroller.getViewport().add(demoSrcPane);

        tabbedPane.addTab(
            getString("TabbedPane.src_label"),
            null,
            scroller,
            getString("TabbedPane.src_tooltip")
        );
    }

    DemoModule currentTabDemo = null;
    class TabListener implements ChangeListener {
        public void stateChanged(ChangeEvent e) {
            SingleSelectionModel model = (SingleSelectionModel) e.getSource();
            boolean srcSelected = model.getSelectedIndex() == 1;
            if(currentTabDemo != currentDemo && demoSrcPane != null && srcSelected) {
                demoSrcPane.setText(getString("SourceCode.loading"));
                repaint();
            }
            if(currentTabDemo != currentDemo && srcSelected) {
                currentTabDemo = currentDemo;
                setSourceCode(currentDemo);
            }
        }
    }


    /**
     * Create menus
     */
    public JMenuBar createMenus() {
        JMenuItem mi;
        // ***** create the menubar ****
        JMenuBar menuBar = new JMenuBar();
        menuBar.getAccessibleContext().setAccessibleName(
            getString("MenuBar.accessible_description"));

        // ***** create File menu
        JMenu fileMenu = (JMenu) menuBar.add(new JMenu(getString("FileMenu.file_label")));
        fileMenu.setMnemonic(getMnemonic("FileMenu.file_mnemonic"));
        fileMenu.getAccessibleContext().setAccessibleDescription(getString("FileMenu.accessible_description"));

        createMenuItem(fileMenu, "FileMenu.about_label", "FileMenu.about_mnemonic",
                       "FileMenu.about_accessible_description", new AboutAction(this));

        fileMenu.addSeparator();

        createMenuItem(fileMenu, "FileMenu.open_label", "FileMenu.open_mnemonic",
                       "FileMenu.open_accessible_description", null);

        createMenuItem(fileMenu, "FileMenu.save_label", "FileMenu.save_mnemonic",
                       "FileMenu.save_accessible_description", null);

        createMenuItem(fileMenu, "FileMenu.save_as_label", "FileMenu.save_as_mnemonic",
                       "FileMenu.save_as_accessible_description", null);


        fileMenu.addSeparator();

        createMenuItem(fileMenu, "FileMenu.exit_label", "FileMenu.exit_mnemonic",
                       "FileMenu.exit_accessible_description", new ExitAction(this)
        );

        // Create these menu items for the first SwingSet only.
        if (numSSs == 0) {
        // ***** create laf switcher menu
        lafMenu = (JMenu) menuBar.add(new JMenu(getString("LafMenu.laf_label")));
        lafMenu.setMnemonic(getMnemonic("LafMenu.laf_mnemonic"));
        lafMenu.getAccessibleContext().setAccessibleDescription(
            getString("LafMenu.laf_accessible_description"));

        for (LookAndFeelData lafData : lookAndFeelData) {
            mi = createLafMenuItem(lafMenu, lafData);
            mi.setSelected(lafData.equals(currentLookAndFeel));
        }

        // ***** create themes menu
        themesMenu = (JMenu) menuBar.add(new JMenu(getString("ThemesMenu.themes_label")));
        themesMenu.setMnemonic(getMnemonic("ThemesMenu.themes_mnemonic"));
        themesMenu.getAccessibleContext().setAccessibleDescription(
            getString("ThemesMenu.themes_accessible_description"));

        // ***** create the audio submenu under the theme menu
        audioMenu = (JMenu) themesMenu.add(new JMenu(getString("AudioMenu.audio_label")));
        audioMenu.setMnemonic(getMnemonic("AudioMenu.audio_mnemonic"));
        audioMenu.getAccessibleContext().setAccessibleDescription(
            getString("AudioMenu.audio_accessible_description"));

        createAudioMenuItem(audioMenu, "AudioMenu.on_label",
                            "AudioMenu.on_mnemonic",
                            "AudioMenu.on_accessible_description",
                            new OnAudioAction(this));

        mi = createAudioMenuItem(audioMenu, "AudioMenu.default_label",
                                 "AudioMenu.default_mnemonic",
                                 "AudioMenu.default_accessible_description",
                                 new DefaultAudioAction(this));
        mi.setSelected(true); // This is the default feedback setting

        createAudioMenuItem(audioMenu, "AudioMenu.off_label",
                            "AudioMenu.off_mnemonic",
                            "AudioMenu.off_accessible_description",
                            new OffAudioAction(this));


        // ***** create the font submenu under the theme menu
        JMenu fontMenu = (JMenu) themesMenu.add(new JMenu(getString("FontMenu.fonts_label")));
        fontMenu.setMnemonic(getMnemonic("FontMenu.fonts_mnemonic"));
        fontMenu.getAccessibleContext().setAccessibleDescription(
            getString("FontMenu.fonts_accessible_description"));
        ButtonGroup fontButtonGroup = new ButtonGroup();
        mi = createButtonGroupMenuItem(fontMenu, "FontMenu.plain_label",
                "FontMenu.plain_mnemonic",
                "FontMenu.plain_accessible_description",
                new ChangeFontAction(this, true), fontButtonGroup);
        mi.setSelected(true);
        mi = createButtonGroupMenuItem(fontMenu, "FontMenu.bold_label",
                "FontMenu.bold_mnemonic",
                "FontMenu.bold_accessible_description",
                new ChangeFontAction(this, false), fontButtonGroup);



        // *** now back to adding color/font themes to the theme menu
        mi = createThemesMenuItem(themesMenu, "ThemesMenu.ocean_label",
                                              "ThemesMenu.ocean_mnemonic",
                                              "ThemesMenu.ocean_accessible_description",
                                              new OceanTheme());
        mi.setSelected(true); // This is the default theme

        createThemesMenuItem(themesMenu, "ThemesMenu.steel_label",
                             "ThemesMenu.steel_mnemonic",
                             "ThemesMenu.steel_accessible_description",
                             new DefaultMetalTheme());

        createThemesMenuItem(themesMenu, "ThemesMenu.aqua_label", "ThemesMenu.aqua_mnemonic",
                       "ThemesMenu.aqua_accessible_description", new AquaTheme());

        createThemesMenuItem(themesMenu, "ThemesMenu.charcoal_label", "ThemesMenu.charcoal_mnemonic",
                       "ThemesMenu.charcoal_accessible_description", new CharcoalTheme());

        createThemesMenuItem(themesMenu, "ThemesMenu.contrast_label", "ThemesMenu.contrast_mnemonic",
                       "ThemesMenu.contrast_accessible_description", new ContrastTheme());

        createThemesMenuItem(themesMenu, "ThemesMenu.emerald_label", "ThemesMenu.emerald_mnemonic",
                       "ThemesMenu.emerald_accessible_description", new EmeraldTheme());

        createThemesMenuItem(themesMenu, "ThemesMenu.ruby_label", "ThemesMenu.ruby_mnemonic",
                       "ThemesMenu.ruby_accessible_description", new RubyTheme());

        // Enable theme menu based on L&F
        themesMenu.setEnabled("Metal".equals(currentLookAndFeel.name));

        // ***** create the options menu
        optionsMenu = (JMenu)menuBar.add(
            new JMenu(getString("OptionsMenu.options_label")));
        optionsMenu.setMnemonic(getMnemonic("OptionsMenu.options_mnemonic"));
        optionsMenu.getAccessibleContext().setAccessibleDescription(
            getString("OptionsMenu.options_accessible_description"));

        // ***** create tool tip submenu item.
        mi = createCheckBoxMenuItem(optionsMenu, "OptionsMenu.tooltip_label",
                "OptionsMenu.tooltip_mnemonic",
                "OptionsMenu.tooltip_accessible_description",
                new ToolTipAction());
        mi.setSelected(true);

        // ***** create drag support submenu item.
        createCheckBoxMenuItem(optionsMenu, "OptionsMenu.dragEnabled_label",
                "OptionsMenu.dragEnabled_mnemonic",
                "OptionsMenu.dragEnabled_accessible_description",
                new DragSupportAction());

        }


        // ***** create the multiscreen menu, if we have multiple screens
        GraphicsDevice[] screens = GraphicsEnvironment.
                                    getLocalGraphicsEnvironment().
                                    getScreenDevices();
        if (screens.length > 1) {

            JMenu multiScreenMenu = (JMenu) menuBar.add(new JMenu(
                                     getString("MultiMenu.multi_label")));

            multiScreenMenu.setMnemonic(getMnemonic("MultiMenu.multi_mnemonic"));
            multiScreenMenu.getAccessibleContext().setAccessibleDescription(
             getString("MultiMenu.multi_accessible_description"));

            createMultiscreenMenuItem(multiScreenMenu, MultiScreenAction.ALL_SCREENS);
            for (int i = 0; i < screens.length; i++) {
                createMultiscreenMenuItem(multiScreenMenu, i);
            }
        }

        return menuBar;
    }

    /**
     * Create a checkbox menu menu item
     */
    private JMenuItem createCheckBoxMenuItem(JMenu menu, String label,
                                             String mnemonic,
                                             String accessibleDescription,
                                             Action action) {
        JCheckBoxMenuItem mi = (JCheckBoxMenuItem)menu.add(
                new JCheckBoxMenuItem(getString(label)));
        mi.setMnemonic(getMnemonic(mnemonic));
        mi.getAccessibleContext().setAccessibleDescription(getString(
                accessibleDescription));
        mi.addActionListener(action);
        return mi;
    }

    /**
     * Create a radio button menu menu item for items that are part of a
     * button group.
     */
    private JMenuItem createButtonGroupMenuItem(JMenu menu, String label,
                                                String mnemonic,
                                                String accessibleDescription,
                                                Action action,
                                                ButtonGroup buttonGroup) {
        JRadioButtonMenuItem mi = (JRadioButtonMenuItem)menu.add(
                new JRadioButtonMenuItem(getString(label)));
        buttonGroup.add(mi);
        mi.setMnemonic(getMnemonic(mnemonic));
        mi.getAccessibleContext().setAccessibleDescription(getString(
                accessibleDescription));
        mi.addActionListener(action);
        return mi;
    }

    /**
     * Create the theme's audio submenu
     */
    public JMenuItem createAudioMenuItem(JMenu menu, String label,
                                         String mnemonic,
                                         String accessibleDescription,
                                         Action action) {
        JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));
        audioMenuGroup.add(mi);
        mi.setMnemonic(getMnemonic(mnemonic));
        mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
        mi.addActionListener(action);

        return mi;
    }

    /**
     * Creates a generic menu item
     */
    public JMenuItem createMenuItem(JMenu menu, String label, String mnemonic,
                               String accessibleDescription, Action action) {
        JMenuItem mi = (JMenuItem) menu.add(new JMenuItem(getString(label)));
        mi.setMnemonic(getMnemonic(mnemonic));
        mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
        mi.addActionListener(action);
        if(action == null) {
            mi.setEnabled(false);
        }
        return mi;
    }

    /**
     * Creates a JRadioButtonMenuItem for the Themes menu
     */
    public JMenuItem createThemesMenuItem(JMenu menu, String label, String mnemonic,
                               String accessibleDescription, MetalTheme theme) {
        JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));
        themesMenuGroup.add(mi);
        mi.setMnemonic(getMnemonic(mnemonic));
        mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));
        mi.addActionListener(new ChangeThemeAction(this, theme));

        return mi;
    }

    /**
     * Creates a JRadioButtonMenuItem for the Look and Feel menu
     */
    public JMenuItem createLafMenuItem(JMenu menu, LookAndFeelData lafData) {
        JMenuItem mi = menu.add(new JRadioButtonMenuItem(lafData.label));
        lafMenuGroup.add(mi);
        mi.setMnemonic(lafData.mnemonic);
        mi.getAccessibleContext().setAccessibleDescription(lafData.accDescription);
        mi.addActionListener(new ChangeLookAndFeelAction(this, lafData));
        return mi;
    }

    /**
     * Creates a multi-screen menu item
     */
    public JMenuItem createMultiscreenMenuItem(JMenu menu, int screen) {
        JMenuItem mi = null;
        if (screen == MultiScreenAction.ALL_SCREENS) {
            mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.all_label")));
            mi.setMnemonic(getMnemonic("MultiMenu.all_mnemonic"));
            mi.getAccessibleContext().setAccessibleDescription(getString(
                                                                 "MultiMenu.all_accessible_description"));
        }
        else {
            mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.single_label") + " " +
                                                                                                 screen));
            mi.setMnemonic(KeyEvent.VK_0 + screen);
            mi.getAccessibleContext().setAccessibleDescription(getString(
                                               "MultiMenu.single_accessible_description") + " " + screen);

        }
        mi.addActionListener(new MultiScreenAction(this, screen));
        return mi;
    }

    public JPopupMenu createPopupMenu() {
        JPopupMenu popup = new JPopupMenu("JPopupMenu demo");

        for (LookAndFeelData lafData : lookAndFeelData) {
            createPopupMenuItem(popup, lafData);
        }

        // register key binding to activate popup menu
        InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        map.put(KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.SHIFT_DOWN_MASK),
                "postMenuAction");
        map.put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTEXT_MENU, 0), "postMenuAction");
        getActionMap().put("postMenuAction", new ActivatePopupMenuAction(this, popup));

        return popup;
    }

    /**
     * Creates a JMenuItem for the Look and Feel popup menu
     */
    public JMenuItem createPopupMenuItem(JPopupMenu menu, LookAndFeelData lafData) {
        JMenuItem mi = menu.add(new JMenuItem(lafData.label));
        popupMenuGroup.add(mi);
        mi.setMnemonic(lafData.mnemonic);
        mi.getAccessibleContext().setAccessibleDescription(lafData.accDescription);
        mi.addActionListener(new ChangeLookAndFeelAction(this, lafData));
        return mi;
    }


    /**
     * Load the first demo. This is done separately from the remaining demos
     * so that we can get SwingSet2 up and available to the user quickly.
     */
    public void preloadFirstDemo() {
        DemoModule demo = addDemo(new InternalFrameDemo(this));
        setDemo(demo);
    }


    /**
     * Add a demo to the toolbar
     */
    public DemoModule addDemo(DemoModule demo) {
        demosList.add(demo);
        if (dragEnabled) {
            demo.updateDragEnabled(true);
        }
        // do the following on the gui thread
        SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {
            public void run() {
                SwitchToDemoAction action = new SwitchToDemoAction(swingset, (DemoModule) obj);
                JToggleButton tb = swingset.getToolBar().addToggleButton(action);
                swingset.getToolBarGroup().add(tb);
                if(swingset.getToolBarGroup().getSelection() == null) {
                    tb.setSelected(true);
                }
                tb.setText(null);
                tb.setToolTipText(((DemoModule)obj).getToolTip());

                if(demos[demos.length-1].equals(obj.getClass().getName())) {
                    setStatus(getString("Status.popupMenuAccessible"));
                }

            }
        });
        return demo;
    }


    /**
     * Sets the current demo
     */
    public void setDemo(DemoModule demo) {
        currentDemo = demo;

        // Ensure panel's UI is current before making visible
        JComponent currentDemoPanel = demo.getDemoPanel();
        SwingUtilities.updateComponentTreeUI(currentDemoPanel);

        demoPanel.removeAll();
        demoPanel.add(currentDemoPanel, BorderLayout.CENTER);

        tabbedPane.setSelectedIndex(0);
        tabbedPane.setTitleAt(0, demo.getName());
        tabbedPane.setToolTipTextAt(0, demo.getToolTip());
    }


    /**
     * Bring up the SwingSet2 demo by showing the frame
     */
    public void showSwingSet2() {
        // put swingset in a frame and show it
        JFrame f = getFrame();
        f.setTitle(getString("Frame.title"));
        f.getContentPane().add(this, BorderLayout.CENTER);
        f.pack();

        Rectangle screenRect = f.getGraphicsConfiguration().getBounds();
        Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(
                f.getGraphicsConfiguration());

        // Make sure we don't place the demo off the screen.
        int centerWidth = screenRect.width < f.getSize().width ?
                screenRect.x :
                screenRect.x + screenRect.width/2 - f.getSize().width/2;
        int centerHeight = screenRect.height < f.getSize().height ?
                screenRect.y :
                screenRect.y + screenRect.height/2 - f.getSize().height/2;

        centerHeight = centerHeight < screenInsets.top ?
                screenInsets.top : centerHeight;

        f.setLocation(centerWidth, centerHeight);
        f.setVisible(true);
        numSSs++;
        swingSets.add(this);
    }

    // *******************************************************
    // ****************** Utility Methods ********************
    // *******************************************************

    /**
     * Loads a demo from a classname
     */
    void loadDemo(String classname) {
        setStatus(getString("Status.loading") + getString(classname + ".name"));
        DemoModule demo = null;
        try {
            Class<?> demoClass = Class.forName(classname);
            Constructor<?> demoConstructor = demoClass.getConstructor(new Class[]{SwingSet2.class});
            demo = (DemoModule) demoConstructor.newInstance(new Object[]{this});
            addDemo(demo);
        } catch (Exception e) {
            System.out.println("Error occurred loading demo: " + classname);
        }
    }

    /**
     * Returns the frame instance
     */
    public JFrame getFrame() {
        return frame;
    }

    /**
     * Returns the menubar
     */
    public JMenuBar getMenuBar() {
        return menuBar;
    }

    /**
     * Returns the toolbar
     */
    public ToggleButtonToolBar getToolBar() {
        return toolbar;
    }

    /**
     * Returns the toolbar button group
     */
    public ButtonGroup getToolBarGroup() {
        return toolbarGroup;
    }

    /**
     * Returns the content pane whether we're in an applet
     * or application
     */
    public Container getContentPane() {
        if(contentPane == null) {
            if(getFrame() != null) {
                contentPane = getFrame().getContentPane();
            }
        }
        return contentPane;
    }

    /**
     * Create a frame for SwingSet2 to reside in if brought up
     * as an application.
     */
    public static JFrame createFrame(GraphicsConfiguration gc) {
        JFrame frame = new JFrame(gc);
        if (numSSs == 0) {
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        } else {
            WindowListener l = new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    numSSs--;
                    swingSets.remove(this);
                }
            };
            frame.addWindowListener(l);
        }
        return frame;
    }


    /**
     * Set the status
     */
    public void setStatus(String s) {
        // do the following on the gui thread
        SwingUtilities.invokeLater(new SwingSetRunnable(this, s) {
            public void run() {
                swingset.statusField.setText((String) obj);
            }
        });
    }


    /**
     * This method returns a string from the demo's resource bundle.
     */
    public static String getString(String key) {
        String value = null;
        try {
            value = TextAndMnemonicUtils.getTextAndMnemonicString(key);
        } catch (MissingResourceException e) {
            System.out.println("java.util.MissingResourceException: Couldn't find value for: " + key);
        }
        if(value == null) {
            value = "Could not find resource: " + key + "  ";
        }
        return value;
    }

    void setDragEnabled(boolean dragEnabled) {
        if (dragEnabled == this.dragEnabled) {
            return;
        }

        this.dragEnabled = dragEnabled;

        for (DemoModule dm : demosList) {
            dm.updateDragEnabled(dragEnabled);
        }

        demoSrcPane.setDragEnabled(dragEnabled);
    }

    boolean isDragEnabled() {
        return dragEnabled;
    }


    /**
     * Returns a mnemonic from the resource bundle. Typically used as
     * keyboard shortcuts in menu items.
     */
    public char getMnemonic(String key) {
        return (getString(key)).charAt(0);
    }

    /**
     * Creates an icon from an image contained in the "images" directory.
     */
    public ImageIcon createImageIcon(String filename, String description) {
        String path = "/resources/images/" + filename;
        return new ImageIcon(getClass().getResource(path));
    }

    /**
     * If DEBUG is defined, prints debug information out to std ouput.
     */
    public void debug(String s) {
        if(DEBUG) {
            System.out.println((debugCounter++) + ": " + s);
        }
    }

    /**
     * Stores the current L&F, and calls updateLookAndFeel, below
     */
    public void setLookAndFeel(LookAndFeelData laf) {
        if(!currentLookAndFeel.equals(laf)) {
            currentLookAndFeel = laf;
            /* The recommended way of synchronizing state between multiple
             * controls that represent the same command is to use Actions.
             * The code below is a workaround and will be replaced in future
             * version of SwingSet2 demo.
             */
            String lafName = laf.label;
            themesMenu.setEnabled(laf.name.equals("Metal"));
            updateLookAndFeel();
            for(int i=0;i<lafMenu.getItemCount();i++) {
                JMenuItem item = lafMenu.getItem(i);
                item.setSelected(item.getText().equals(lafName));
            }
        }
    }

    private void updateThisSwingSet() {
        JFrame frame = getFrame();
        if (frame == null) {
            SwingUtilities.updateComponentTreeUI(this);
        } else {
            if (currentLookAndFeel.name.contains("GTK")) {
                this.setPreferredSize(new Dimension(PREFERRED_WIDTH + 260, PREFERRED_HEIGHT + 80));
            } else {
                this.setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));
            }

            SwingUtilities.updateComponentTreeUI(frame);
            frame.pack();
        }

        SwingUtilities.updateComponentTreeUI(popupMenu);
        if (aboutBox != null) {
            SwingUtilities.updateComponentTreeUI(aboutBox);
        }
    }

    /**
     * Sets the current L&F on each demo module
     */
    public void updateLookAndFeel() {
        try {
            UIManager.setLookAndFeel(currentLookAndFeel.className);
            for (SwingSet2 ss : swingSets) {
                ss.updateThisSwingSet();
            }
        } catch (Exception ex) {
            System.out.println("Failed loading L&F: " + currentLookAndFeel);
            System.out.println(ex);
        }
    }

    /**
     * Loads and puts the source code text into JEditorPane in the "Source Code" tab
     */
    public void setSourceCode(DemoModule demo) {
        // do the following on the gui thread
        SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {
            public void run() {
                swingset.demoSrcPane.setText(((DemoModule)obj).getSourceCode());
                swingset.demoSrcPane.setCaretPosition(0);

            }
        });
    }

    // *******************************************************
    // **************   ToggleButtonToolbar  *****************
    // *******************************************************
    static Insets zeroInsets = new Insets(1,1,1,1);
    protected class ToggleButtonToolBar extends JToolBar {
        public ToggleButtonToolBar() {
            super();
        }

        JToggleButton addToggleButton(Action a) {
            JToggleButton tb = new JToggleButton(
                (String)a.getValue(Action.NAME),
                (Icon)a.getValue(Action.SMALL_ICON)
            );
            tb.setMargin(zeroInsets);
            tb.setText(null);
            tb.setEnabled(a.isEnabled());
            tb.setToolTipText((String)a.getValue(Action.SHORT_DESCRIPTION));
            tb.setAction(a);
            add(tb);
            return tb;
        }
    }

    // *******************************************************
    // *********  ToolBar Panel / Docking Listener ***********
    // *******************************************************
    class ToolBarPanel extends JPanel implements ContainerListener {

        public boolean contains(int x, int y) {
            Component c = getParent();
            if (c != null) {
                Rectangle r = c.getBounds();
                return (x >= 0) && (x < r.width) && (y >= 0) && (y < r.height);
            }
            else {
                return super.contains(x,y);
            }
        }

        public void componentAdded(ContainerEvent e) {
            Container c = e.getContainer().getParent();
            if (c != null) {
                c.getParent().validate();
                c.getParent().repaint();
            }
        }

        public void componentRemoved(ContainerEvent e) {
            Container c = e.getContainer().getParent();
            if (c != null) {
                c.getParent().validate();
                c.getParent().repaint();
            }
        }
    }

    // *******************************************************
    // ******************   Runnables  ***********************
    // *******************************************************

    /**
     * Generic SwingSet2 runnable. This is intended to run on the
     * AWT gui event thread so as not to muck things up by doing
     * gui work off the gui thread. Accepts a SwingSet2 and an Object
     * as arguments, which gives subtypes of this class the two
     * "must haves" needed in most runnables for this demo.
     */
    class SwingSetRunnable implements Runnable {
        protected SwingSet2 swingset;
        protected Object obj;

        public SwingSetRunnable(SwingSet2 swingset, Object obj) {
            this.swingset = swingset;
            this.obj = obj;
        }

        public void run() {
        }
    }


    // *******************************************************
    // ********************   Actions  ***********************
    // *******************************************************

    public class SwitchToDemoAction extends AbstractAction {
        SwingSet2 swingset;
        DemoModule demo;

        public SwitchToDemoAction(SwingSet2 swingset, DemoModule demo) {
            super(demo.getName(), demo.getIcon());
            this.swingset = swingset;
            this.demo = demo;
        }

        public void actionPerformed(ActionEvent e) {
            swingset.setDemo(demo);
        }
    }

    class OkAction extends AbstractAction {
        JDialog aboutBox;

        protected OkAction(JDialog aboutBox) {
            super("OkAction");
            this.aboutBox = aboutBox;
        }

        public void actionPerformed(ActionEvent e) {
            aboutBox.setVisible(false);
        }
    }

    class ChangeLookAndFeelAction extends AbstractAction {
        SwingSet2 swingset;
        LookAndFeelData lafData;
        protected ChangeLookAndFeelAction(SwingSet2 swingset, LookAndFeelData lafData) {
            super("ChangeTheme");
            this.swingset = swingset;
            this.lafData = lafData;
        }

        public void actionPerformed(ActionEvent e) {
            swingset.setLookAndFeel(lafData);
        }
    }

    class ActivatePopupMenuAction extends AbstractAction {
        SwingSet2 swingset;
        JPopupMenu popup;
        protected ActivatePopupMenuAction(SwingSet2 swingset, JPopupMenu popup) {
            super("ActivatePopupMenu");
            this.swingset = swingset;
            this.popup = popup;
        }

        public void actionPerformed(ActionEvent e) {
            Dimension invokerSize = getSize();
            Dimension popupSize = popup.getPreferredSize();
            popup.show(swingset, (invokerSize.width - popupSize.width) / 2,
                       (invokerSize.height - popupSize.height) / 2);
        }
    }

    // Turns on all possible auditory feedback
    class OnAudioAction extends AbstractAction {
        SwingSet2 swingset;
        protected OnAudioAction(SwingSet2 swingset) {
            super("Audio On");
            this.swingset = swingset;
        }
        public void actionPerformed(ActionEvent e) {
            UIManager.put("AuditoryCues.playList",
                          UIManager.get("AuditoryCues.allAuditoryCues"));
            swingset.updateLookAndFeel();
        }
    }

    // Turns on the default amount of auditory feedback
    class DefaultAudioAction extends AbstractAction {
        SwingSet2 swingset;
        protected DefaultAudioAction(SwingSet2 swingset) {
            super("Audio Default");
            this.swingset = swingset;
        }
        public void actionPerformed(ActionEvent e) {
            UIManager.put("AuditoryCues.playList",
                          UIManager.get("AuditoryCues.defaultCueList"));
            swingset.updateLookAndFeel();
        }
    }

    // Turns off all possible auditory feedback
    class OffAudioAction extends AbstractAction {
        SwingSet2 swingset;
        protected OffAudioAction(SwingSet2 swingset) {
            super("Audio Off");
            this.swingset = swingset;
        }
        public void actionPerformed(ActionEvent e) {
            UIManager.put("AuditoryCues.playList",
                          UIManager.get("AuditoryCues.noAuditoryCues"));
            swingset.updateLookAndFeel();
        }
    }

    // Turns on or off the tool tips for the demo.
    class ToolTipAction extends AbstractAction {
        protected ToolTipAction() {
            super("ToolTip Control");
        }

        public void actionPerformed(ActionEvent e) {
            boolean status = ((JCheckBoxMenuItem)e.getSource()).isSelected();
            ToolTipManager.sharedInstance().setEnabled(status);
        }
    }

    class DragSupportAction extends AbstractAction {
        protected DragSupportAction() {
            super("DragSupport Control");
        }

        public void actionPerformed(ActionEvent e) {
            boolean dragEnabled = ((JCheckBoxMenuItem)e.getSource()).isSelected();
            for (SwingSet2 ss : swingSets) {
                ss.setDragEnabled(dragEnabled);
            }
        }
    }

    class ChangeThemeAction extends AbstractAction {
        SwingSet2 swingset;
        MetalTheme theme;
        protected ChangeThemeAction(SwingSet2 swingset, MetalTheme theme) {
            super("ChangeTheme");
            this.swingset = swingset;
            this.theme = theme;
        }

        public void actionPerformed(ActionEvent e) {
            MetalLookAndFeel.setCurrentTheme(theme);
            swingset.updateLookAndFeel();
        }
    }

    class ExitAction extends AbstractAction {
        SwingSet2 swingset;
        protected ExitAction(SwingSet2 swingset) {
            super("ExitAction");
            this.swingset = swingset;
        }

        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }

    class AboutAction extends AbstractAction {
        SwingSet2 swingset;
        protected AboutAction(SwingSet2 swingset) {
            super("AboutAction");
            this.swingset = swingset;
        }

        public void actionPerformed(ActionEvent e) {
            if(aboutBox == null) {
                // JPanel panel = new JPanel(new BorderLayout());
                JPanel panel = new AboutPanel(swingset);
                panel.setLayout(new BorderLayout());

                aboutBox = new JDialog(swingset.getFrame(), getString("AboutBox.title"), false);
                aboutBox.setResizable(false);
                aboutBox.getContentPane().add(panel, BorderLayout.CENTER);

                // JButton button = new JButton(getString("AboutBox.ok_button_text"));
                JPanel buttonpanel = new JPanel();
                buttonpanel.setBorder(new javax.swing.border.EmptyBorder(0, 0, 3, 0));
                buttonpanel.setOpaque(false);
                JButton button = (JButton) buttonpanel.add(
                    new JButton(getString("AboutBox.ok_button_text"))
                );
                panel.add(buttonpanel, BorderLayout.SOUTH);

                button.addActionListener(new OkAction(aboutBox));
            }
            aboutBox.pack();
            aboutBox.setLocationRelativeTo(getFrame());
            aboutBox.setVisible(true);
        }
    }

    class MultiScreenAction extends AbstractAction {
        static final int ALL_SCREENS = -1;
        int screen;
        protected MultiScreenAction(SwingSet2 swingset, int screen) {
            super("MultiScreenAction");
            this.screen = screen;
        }

        public void actionPerformed(ActionEvent e) {
            GraphicsDevice[] gds = GraphicsEnvironment.
                                   getLocalGraphicsEnvironment().
                                   getScreenDevices();
            if (screen == ALL_SCREENS) {
                for (int i = 0; i < gds.length; i++) {
                    SwingSet2 swingset = new SwingSet2(
                                  gds[i].getDefaultConfiguration());
                    swingset.setDragEnabled(dragEnabled);
                }
            }
            else {
                SwingSet2 swingset = new SwingSet2(
                             gds[screen].getDefaultConfiguration());
                swingset.setDragEnabled(dragEnabled);
            }
        }
    }

    // *******************************************************
    // **********************  Misc  *************************
    // *******************************************************

    class DemoLoadThread extends Thread {
        SwingSet2 swingset;

        DemoLoadThread(SwingSet2 swingset) {
            this.swingset = swingset;
        }

        public void run() {
            SwingUtilities.invokeLater(swingset::loadDemos);
        }
    }

    class AboutPanel extends JPanel {
        ImageIcon aboutimage = null;
        SwingSet2 swingset = null;

        public AboutPanel(SwingSet2 swingset) {
            this.swingset = swingset;
            aboutimage = swingset.createImageIcon("About.jpg", "AboutBox.accessible_description");
            setOpaque(false);
        }

        public void paint(Graphics g) {
            aboutimage.paintIcon(this, g, 0, 0);
            super.paint(g);
        }

        public Dimension getPreferredSize() {
            return new Dimension(aboutimage.getIconWidth(),
                                 aboutimage.getIconHeight());
        }
    }


    private class ChangeFontAction extends AbstractAction {
        private SwingSet2 swingset;
        private boolean plain;

        ChangeFontAction(SwingSet2 swingset, boolean plain) {
            super("FontMenu");
            this.swingset = swingset;
            this.plain = plain;
        }

        public void actionPerformed(ActionEvent e) {
            if (plain) {
                UIManager.put("swing.boldMetal", Boolean.FALSE);
            }
            else {
                UIManager.put("swing.boldMetal", Boolean.TRUE);
            }
            // Change the look and feel to force the settings to take effect.
            updateLookAndFeel();
        }
    }

    private static LookAndFeelData[] getInstalledLookAndFeelData() {
        return Arrays.stream(UIManager.getInstalledLookAndFeels())
                .map(laf -> getLookAndFeelData(laf))
                .toArray(LookAndFeelData[]::new);
    }

    private static LookAndFeelData getLookAndFeelData(
            UIManager.LookAndFeelInfo info) {
        switch (info.getName()) {
            case "Metal":
                return new LookAndFeelData(info, "java");
            case "Nimbus":
                return new LookAndFeelData(info, "nimbus");
            case "Windows":
                return new LookAndFeelData(info, "windows");
            case "GTK+":
                return new LookAndFeelData(info, "gtk");
            case "CDE/Motif":
                return new LookAndFeelData(info, "motif");
            case "Mac OS X":
                return new LookAndFeelData(info, "mac");
            default:
                return new LookAndFeelData(info);
        }
    }

    private static class LookAndFeelData {
        String name;
        String className;
        String label;
        char mnemonic;
        String accDescription;

        public LookAndFeelData(UIManager.LookAndFeelInfo info) {
            this(info.getName(), info.getClassName(), info.getName(),
                 info.getName(), info.getName());
        }

        public LookAndFeelData(UIManager.LookAndFeelInfo info, String property) {
            this(info.getName(), info.getClassName(),
                    getString(String.format("LafMenu.%s_label", property)),
                    getString(String.format("LafMenu.%s_mnemonic", property)),
                    getString(String.format("LafMenu.%s_accessible_description",
                                    property)));
        }

        public LookAndFeelData(String name, String className, String label,
                               String mnemonic, String accDescription) {
            this.name = name;
            this.className = className;
            this.label = label;
            this.mnemonic = mnemonic.charAt(0);
            this.accDescription = accDescription;
        }

        @Override
        public String toString() {
            return className;
        }
    }
}
