Path: blob/master/src/demo/share/jfc/SwingSet2/SwingSet2.java
41152 views
/*1*2* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7*8* - Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10*11* - Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* - Neither the name of Oracle nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS20* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,21* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR22* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR23* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,24* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,25* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR26* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF27* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING28* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132import javax.swing.*;33import javax.swing.event.*;34import javax.swing.border.*;3536import javax.swing.plaf.metal.MetalTheme;37import javax.swing.plaf.metal.OceanTheme;38import javax.swing.plaf.metal.DefaultMetalTheme;39import javax.swing.plaf.metal.MetalLookAndFeel;4041import java.lang.reflect.*;42import java.awt.*;43import java.awt.event.*;44import java.util.*;4546/**47* A demo that shows all of the Swing components.48*49* @author Jeff Dinkins50*/51public class SwingSet2 extends JPanel {5253String[] demos = {54"ButtonDemo",55"ColorChooserDemo",56"ComboBoxDemo",57"FileChooserDemo",58"HtmlDemo",59"ListDemo",60"OptionPaneDemo",61"ProgressBarDemo",62"ScrollPaneDemo",63"SliderDemo",64"SplitPaneDemo",65"TabbedPaneDemo",66"TableDemo",67"ToolTipDemo",68"TreeDemo"69};7071void loadDemos() {72for(int i = 0; i < demos.length;) {73loadDemo(demos[i]);74i++;75}76}7778// The current Look & Feel79private static LookAndFeelData currentLookAndFeel;80private static LookAndFeelData[] lookAndFeelData;81// List of demos82private ArrayList<DemoModule> demosList = new ArrayList<DemoModule>();8384// The preferred size of the demo85private static final int PREFERRED_WIDTH = 720;86private static final int PREFERRED_HEIGHT = 640;8788// Box spacers89private Dimension HGAP = new Dimension(1,5);90private Dimension VGAP = new Dimension(5,1);9192// A place to hold on to the visible demo93private DemoModule currentDemo = null;94private JPanel demoPanel = null;9596// About Box97private JDialog aboutBox = null;9899// Status Bar100private JTextField statusField = null;101102// Tool Bar103private ToggleButtonToolBar toolbar = null;104private ButtonGroup toolbarGroup = new ButtonGroup();105106// Menus107private JMenuBar menuBar = null;108private JMenu lafMenu = null;109private JMenu themesMenu = null;110private JMenu audioMenu = null;111private JMenu optionsMenu = null;112private ButtonGroup lafMenuGroup = new ButtonGroup();113private ButtonGroup themesMenuGroup = new ButtonGroup();114private ButtonGroup audioMenuGroup = new ButtonGroup();115116// Popup menu117private JPopupMenu popupMenu = null;118private ButtonGroup popupMenuGroup = new ButtonGroup();119120// Used only if swingset is an application121private JFrame frame = null;122123// To debug or not to debug, that is the question124private boolean DEBUG = true;125private int debugCounter = 0;126127// The tab pane that holds the demo128private JTabbedPane tabbedPane = null;129130private JEditorPane demoSrcPane = null;131132133// contentPane cache, saved from the applet or application frame134Container contentPane = null;135136137// number of swingsets - for multiscreen138// keep track of the number of SwingSets created - we only want to exit139// the program when the last one has been closed.140private static int numSSs = 0;141private static Vector<SwingSet2> swingSets = new Vector<SwingSet2>();142143private boolean dragEnabled = false;144145public SwingSet2() {146this(null);147}148149/**150* SwingSet2 Constructor151*/152public SwingSet2(GraphicsConfiguration gc) {153String lafClassName = UIManager.getLookAndFeel().getClass().getName();154lookAndFeelData = getInstalledLookAndFeelData();155currentLookAndFeel = Arrays.stream(lookAndFeelData)156.filter(laf -> lafClassName.equals(laf.className))157.findFirst().get();158159frame = createFrame(gc);160161// set the layout162setLayout(new BorderLayout());163164// set the preferred size of the demo165setPreferredSize(new Dimension(PREFERRED_WIDTH,PREFERRED_HEIGHT));166167initializeDemo();168preloadFirstDemo();169170showSwingSet2();171172// Start loading the rest of the demo in the background173DemoLoadThread demoLoader = new DemoLoadThread(this);174demoLoader.start();175}176177178/**179* SwingSet2 Main. Called only if we're an application, not an applet.180*/181public static void main(final String[] args) {182// must run in EDT when constructing the GUI components183SwingUtilities.invokeLater(() -> {184// Create SwingSet on the default monitor185UIManager.put("swing.boldMetal", Boolean.FALSE);186SwingSet2 swingset = new SwingSet2(GraphicsEnvironment.187getLocalGraphicsEnvironment().188getDefaultScreenDevice().189getDefaultConfiguration());190});191}192193// *******************************************************194// *************** Demo Loading Methods ******************195// *******************************************************196197198199public void initializeDemo() {200JPanel top = new JPanel();201top.setLayout(new BorderLayout());202add(top, BorderLayout.NORTH);203204menuBar = createMenus();205206frame.setJMenuBar(menuBar);207208// creates popup menu accessible via keyboard209popupMenu = createPopupMenu();210211ToolBarPanel toolbarPanel = new ToolBarPanel();212toolbarPanel.setLayout(new BorderLayout());213toolbar = new ToggleButtonToolBar();214toolbarPanel.add(toolbar, BorderLayout.CENTER);215top.add(toolbarPanel, BorderLayout.SOUTH);216toolbarPanel.addContainerListener(toolbarPanel);217218tabbedPane = new JTabbedPane();219add(tabbedPane, BorderLayout.CENTER);220tabbedPane.getModel().addChangeListener(new TabListener());221222statusField = new JTextField("");223statusField.setEditable(false);224add(statusField, BorderLayout.SOUTH);225226demoPanel = new JPanel();227demoPanel.setLayout(new BorderLayout());228demoPanel.setBorder(new EtchedBorder());229tabbedPane.addTab("Hi There!", demoPanel);230231// Add html src code viewer232demoSrcPane = new JEditorPane("text/html", getString("SourceCode.loading"));233demoSrcPane.setEditable(false);234235JScrollPane scroller = new JScrollPane();236scroller.getViewport().add(demoSrcPane);237238tabbedPane.addTab(239getString("TabbedPane.src_label"),240null,241scroller,242getString("TabbedPane.src_tooltip")243);244}245246DemoModule currentTabDemo = null;247class TabListener implements ChangeListener {248public void stateChanged(ChangeEvent e) {249SingleSelectionModel model = (SingleSelectionModel) e.getSource();250boolean srcSelected = model.getSelectedIndex() == 1;251if(currentTabDemo != currentDemo && demoSrcPane != null && srcSelected) {252demoSrcPane.setText(getString("SourceCode.loading"));253repaint();254}255if(currentTabDemo != currentDemo && srcSelected) {256currentTabDemo = currentDemo;257setSourceCode(currentDemo);258}259}260}261262263/**264* Create menus265*/266public JMenuBar createMenus() {267JMenuItem mi;268// ***** create the menubar ****269JMenuBar menuBar = new JMenuBar();270menuBar.getAccessibleContext().setAccessibleName(271getString("MenuBar.accessible_description"));272273// ***** create File menu274JMenu fileMenu = (JMenu) menuBar.add(new JMenu(getString("FileMenu.file_label")));275fileMenu.setMnemonic(getMnemonic("FileMenu.file_mnemonic"));276fileMenu.getAccessibleContext().setAccessibleDescription(getString("FileMenu.accessible_description"));277278createMenuItem(fileMenu, "FileMenu.about_label", "FileMenu.about_mnemonic",279"FileMenu.about_accessible_description", new AboutAction(this));280281fileMenu.addSeparator();282283createMenuItem(fileMenu, "FileMenu.open_label", "FileMenu.open_mnemonic",284"FileMenu.open_accessible_description", null);285286createMenuItem(fileMenu, "FileMenu.save_label", "FileMenu.save_mnemonic",287"FileMenu.save_accessible_description", null);288289createMenuItem(fileMenu, "FileMenu.save_as_label", "FileMenu.save_as_mnemonic",290"FileMenu.save_as_accessible_description", null);291292293fileMenu.addSeparator();294295createMenuItem(fileMenu, "FileMenu.exit_label", "FileMenu.exit_mnemonic",296"FileMenu.exit_accessible_description", new ExitAction(this)297);298299// Create these menu items for the first SwingSet only.300if (numSSs == 0) {301// ***** create laf switcher menu302lafMenu = (JMenu) menuBar.add(new JMenu(getString("LafMenu.laf_label")));303lafMenu.setMnemonic(getMnemonic("LafMenu.laf_mnemonic"));304lafMenu.getAccessibleContext().setAccessibleDescription(305getString("LafMenu.laf_accessible_description"));306307for (LookAndFeelData lafData : lookAndFeelData) {308mi = createLafMenuItem(lafMenu, lafData);309mi.setSelected(lafData.equals(currentLookAndFeel));310}311312// ***** create themes menu313themesMenu = (JMenu) menuBar.add(new JMenu(getString("ThemesMenu.themes_label")));314themesMenu.setMnemonic(getMnemonic("ThemesMenu.themes_mnemonic"));315themesMenu.getAccessibleContext().setAccessibleDescription(316getString("ThemesMenu.themes_accessible_description"));317318// ***** create the audio submenu under the theme menu319audioMenu = (JMenu) themesMenu.add(new JMenu(getString("AudioMenu.audio_label")));320audioMenu.setMnemonic(getMnemonic("AudioMenu.audio_mnemonic"));321audioMenu.getAccessibleContext().setAccessibleDescription(322getString("AudioMenu.audio_accessible_description"));323324createAudioMenuItem(audioMenu, "AudioMenu.on_label",325"AudioMenu.on_mnemonic",326"AudioMenu.on_accessible_description",327new OnAudioAction(this));328329mi = createAudioMenuItem(audioMenu, "AudioMenu.default_label",330"AudioMenu.default_mnemonic",331"AudioMenu.default_accessible_description",332new DefaultAudioAction(this));333mi.setSelected(true); // This is the default feedback setting334335createAudioMenuItem(audioMenu, "AudioMenu.off_label",336"AudioMenu.off_mnemonic",337"AudioMenu.off_accessible_description",338new OffAudioAction(this));339340341// ***** create the font submenu under the theme menu342JMenu fontMenu = (JMenu) themesMenu.add(new JMenu(getString("FontMenu.fonts_label")));343fontMenu.setMnemonic(getMnemonic("FontMenu.fonts_mnemonic"));344fontMenu.getAccessibleContext().setAccessibleDescription(345getString("FontMenu.fonts_accessible_description"));346ButtonGroup fontButtonGroup = new ButtonGroup();347mi = createButtonGroupMenuItem(fontMenu, "FontMenu.plain_label",348"FontMenu.plain_mnemonic",349"FontMenu.plain_accessible_description",350new ChangeFontAction(this, true), fontButtonGroup);351mi.setSelected(true);352mi = createButtonGroupMenuItem(fontMenu, "FontMenu.bold_label",353"FontMenu.bold_mnemonic",354"FontMenu.bold_accessible_description",355new ChangeFontAction(this, false), fontButtonGroup);356357358359// *** now back to adding color/font themes to the theme menu360mi = createThemesMenuItem(themesMenu, "ThemesMenu.ocean_label",361"ThemesMenu.ocean_mnemonic",362"ThemesMenu.ocean_accessible_description",363new OceanTheme());364mi.setSelected(true); // This is the default theme365366createThemesMenuItem(themesMenu, "ThemesMenu.steel_label",367"ThemesMenu.steel_mnemonic",368"ThemesMenu.steel_accessible_description",369new DefaultMetalTheme());370371createThemesMenuItem(themesMenu, "ThemesMenu.aqua_label", "ThemesMenu.aqua_mnemonic",372"ThemesMenu.aqua_accessible_description", new AquaTheme());373374createThemesMenuItem(themesMenu, "ThemesMenu.charcoal_label", "ThemesMenu.charcoal_mnemonic",375"ThemesMenu.charcoal_accessible_description", new CharcoalTheme());376377createThemesMenuItem(themesMenu, "ThemesMenu.contrast_label", "ThemesMenu.contrast_mnemonic",378"ThemesMenu.contrast_accessible_description", new ContrastTheme());379380createThemesMenuItem(themesMenu, "ThemesMenu.emerald_label", "ThemesMenu.emerald_mnemonic",381"ThemesMenu.emerald_accessible_description", new EmeraldTheme());382383createThemesMenuItem(themesMenu, "ThemesMenu.ruby_label", "ThemesMenu.ruby_mnemonic",384"ThemesMenu.ruby_accessible_description", new RubyTheme());385386// Enable theme menu based on L&F387themesMenu.setEnabled("Metal".equals(currentLookAndFeel.name));388389// ***** create the options menu390optionsMenu = (JMenu)menuBar.add(391new JMenu(getString("OptionsMenu.options_label")));392optionsMenu.setMnemonic(getMnemonic("OptionsMenu.options_mnemonic"));393optionsMenu.getAccessibleContext().setAccessibleDescription(394getString("OptionsMenu.options_accessible_description"));395396// ***** create tool tip submenu item.397mi = createCheckBoxMenuItem(optionsMenu, "OptionsMenu.tooltip_label",398"OptionsMenu.tooltip_mnemonic",399"OptionsMenu.tooltip_accessible_description",400new ToolTipAction());401mi.setSelected(true);402403// ***** create drag support submenu item.404createCheckBoxMenuItem(optionsMenu, "OptionsMenu.dragEnabled_label",405"OptionsMenu.dragEnabled_mnemonic",406"OptionsMenu.dragEnabled_accessible_description",407new DragSupportAction());408409}410411412// ***** create the multiscreen menu, if we have multiple screens413GraphicsDevice[] screens = GraphicsEnvironment.414getLocalGraphicsEnvironment().415getScreenDevices();416if (screens.length > 1) {417418JMenu multiScreenMenu = (JMenu) menuBar.add(new JMenu(419getString("MultiMenu.multi_label")));420421multiScreenMenu.setMnemonic(getMnemonic("MultiMenu.multi_mnemonic"));422multiScreenMenu.getAccessibleContext().setAccessibleDescription(423getString("MultiMenu.multi_accessible_description"));424425createMultiscreenMenuItem(multiScreenMenu, MultiScreenAction.ALL_SCREENS);426for (int i = 0; i < screens.length; i++) {427createMultiscreenMenuItem(multiScreenMenu, i);428}429}430431return menuBar;432}433434/**435* Create a checkbox menu menu item436*/437private JMenuItem createCheckBoxMenuItem(JMenu menu, String label,438String mnemonic,439String accessibleDescription,440Action action) {441JCheckBoxMenuItem mi = (JCheckBoxMenuItem)menu.add(442new JCheckBoxMenuItem(getString(label)));443mi.setMnemonic(getMnemonic(mnemonic));444mi.getAccessibleContext().setAccessibleDescription(getString(445accessibleDescription));446mi.addActionListener(action);447return mi;448}449450/**451* Create a radio button menu menu item for items that are part of a452* button group.453*/454private JMenuItem createButtonGroupMenuItem(JMenu menu, String label,455String mnemonic,456String accessibleDescription,457Action action,458ButtonGroup buttonGroup) {459JRadioButtonMenuItem mi = (JRadioButtonMenuItem)menu.add(460new JRadioButtonMenuItem(getString(label)));461buttonGroup.add(mi);462mi.setMnemonic(getMnemonic(mnemonic));463mi.getAccessibleContext().setAccessibleDescription(getString(464accessibleDescription));465mi.addActionListener(action);466return mi;467}468469/**470* Create the theme's audio submenu471*/472public JMenuItem createAudioMenuItem(JMenu menu, String label,473String mnemonic,474String accessibleDescription,475Action action) {476JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));477audioMenuGroup.add(mi);478mi.setMnemonic(getMnemonic(mnemonic));479mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));480mi.addActionListener(action);481482return mi;483}484485/**486* Creates a generic menu item487*/488public JMenuItem createMenuItem(JMenu menu, String label, String mnemonic,489String accessibleDescription, Action action) {490JMenuItem mi = (JMenuItem) menu.add(new JMenuItem(getString(label)));491mi.setMnemonic(getMnemonic(mnemonic));492mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));493mi.addActionListener(action);494if(action == null) {495mi.setEnabled(false);496}497return mi;498}499500/**501* Creates a JRadioButtonMenuItem for the Themes menu502*/503public JMenuItem createThemesMenuItem(JMenu menu, String label, String mnemonic,504String accessibleDescription, MetalTheme theme) {505JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));506themesMenuGroup.add(mi);507mi.setMnemonic(getMnemonic(mnemonic));508mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));509mi.addActionListener(new ChangeThemeAction(this, theme));510511return mi;512}513514/**515* Creates a JRadioButtonMenuItem for the Look and Feel menu516*/517public JMenuItem createLafMenuItem(JMenu menu, LookAndFeelData lafData) {518JMenuItem mi = menu.add(new JRadioButtonMenuItem(lafData.label));519lafMenuGroup.add(mi);520mi.setMnemonic(lafData.mnemonic);521mi.getAccessibleContext().setAccessibleDescription(lafData.accDescription);522mi.addActionListener(new ChangeLookAndFeelAction(this, lafData));523return mi;524}525526/**527* Creates a multi-screen menu item528*/529public JMenuItem createMultiscreenMenuItem(JMenu menu, int screen) {530JMenuItem mi = null;531if (screen == MultiScreenAction.ALL_SCREENS) {532mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.all_label")));533mi.setMnemonic(getMnemonic("MultiMenu.all_mnemonic"));534mi.getAccessibleContext().setAccessibleDescription(getString(535"MultiMenu.all_accessible_description"));536}537else {538mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.single_label") + " " +539screen));540mi.setMnemonic(KeyEvent.VK_0 + screen);541mi.getAccessibleContext().setAccessibleDescription(getString(542"MultiMenu.single_accessible_description") + " " + screen);543544}545mi.addActionListener(new MultiScreenAction(this, screen));546return mi;547}548549public JPopupMenu createPopupMenu() {550JPopupMenu popup = new JPopupMenu("JPopupMenu demo");551552for (LookAndFeelData lafData : lookAndFeelData) {553createPopupMenuItem(popup, lafData);554}555556// register key binding to activate popup menu557InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);558map.put(KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.SHIFT_DOWN_MASK),559"postMenuAction");560map.put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTEXT_MENU, 0), "postMenuAction");561getActionMap().put("postMenuAction", new ActivatePopupMenuAction(this, popup));562563return popup;564}565566/**567* Creates a JMenuItem for the Look and Feel popup menu568*/569public JMenuItem createPopupMenuItem(JPopupMenu menu, LookAndFeelData lafData) {570JMenuItem mi = menu.add(new JMenuItem(lafData.label));571popupMenuGroup.add(mi);572mi.setMnemonic(lafData.mnemonic);573mi.getAccessibleContext().setAccessibleDescription(lafData.accDescription);574mi.addActionListener(new ChangeLookAndFeelAction(this, lafData));575return mi;576}577578579/**580* Load the first demo. This is done separately from the remaining demos581* so that we can get SwingSet2 up and available to the user quickly.582*/583public void preloadFirstDemo() {584DemoModule demo = addDemo(new InternalFrameDemo(this));585setDemo(demo);586}587588589/**590* Add a demo to the toolbar591*/592public DemoModule addDemo(DemoModule demo) {593demosList.add(demo);594if (dragEnabled) {595demo.updateDragEnabled(true);596}597// do the following on the gui thread598SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {599public void run() {600SwitchToDemoAction action = new SwitchToDemoAction(swingset, (DemoModule) obj);601JToggleButton tb = swingset.getToolBar().addToggleButton(action);602swingset.getToolBarGroup().add(tb);603if(swingset.getToolBarGroup().getSelection() == null) {604tb.setSelected(true);605}606tb.setText(null);607tb.setToolTipText(((DemoModule)obj).getToolTip());608609if(demos[demos.length-1].equals(obj.getClass().getName())) {610setStatus(getString("Status.popupMenuAccessible"));611}612613}614});615return demo;616}617618619/**620* Sets the current demo621*/622public void setDemo(DemoModule demo) {623currentDemo = demo;624625// Ensure panel's UI is current before making visible626JComponent currentDemoPanel = demo.getDemoPanel();627SwingUtilities.updateComponentTreeUI(currentDemoPanel);628629demoPanel.removeAll();630demoPanel.add(currentDemoPanel, BorderLayout.CENTER);631632tabbedPane.setSelectedIndex(0);633tabbedPane.setTitleAt(0, demo.getName());634tabbedPane.setToolTipTextAt(0, demo.getToolTip());635}636637638/**639* Bring up the SwingSet2 demo by showing the frame640*/641public void showSwingSet2() {642// put swingset in a frame and show it643JFrame f = getFrame();644f.setTitle(getString("Frame.title"));645f.getContentPane().add(this, BorderLayout.CENTER);646f.pack();647648Rectangle screenRect = f.getGraphicsConfiguration().getBounds();649Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(650f.getGraphicsConfiguration());651652// Make sure we don't place the demo off the screen.653int centerWidth = screenRect.width < f.getSize().width ?654screenRect.x :655screenRect.x + screenRect.width/2 - f.getSize().width/2;656int centerHeight = screenRect.height < f.getSize().height ?657screenRect.y :658screenRect.y + screenRect.height/2 - f.getSize().height/2;659660centerHeight = centerHeight < screenInsets.top ?661screenInsets.top : centerHeight;662663f.setLocation(centerWidth, centerHeight);664f.setVisible(true);665numSSs++;666swingSets.add(this);667}668669// *******************************************************670// ****************** Utility Methods ********************671// *******************************************************672673/**674* Loads a demo from a classname675*/676void loadDemo(String classname) {677setStatus(getString("Status.loading") + getString(classname + ".name"));678DemoModule demo = null;679try {680Class<?> demoClass = Class.forName(classname);681Constructor<?> demoConstructor = demoClass.getConstructor(new Class[]{SwingSet2.class});682demo = (DemoModule) demoConstructor.newInstance(new Object[]{this});683addDemo(demo);684} catch (Exception e) {685System.out.println("Error occurred loading demo: " + classname);686}687}688689/**690* Returns the frame instance691*/692public JFrame getFrame() {693return frame;694}695696/**697* Returns the menubar698*/699public JMenuBar getMenuBar() {700return menuBar;701}702703/**704* Returns the toolbar705*/706public ToggleButtonToolBar getToolBar() {707return toolbar;708}709710/**711* Returns the toolbar button group712*/713public ButtonGroup getToolBarGroup() {714return toolbarGroup;715}716717/**718* Returns the content pane whether we're in an applet719* or application720*/721public Container getContentPane() {722if(contentPane == null) {723if(getFrame() != null) {724contentPane = getFrame().getContentPane();725}726}727return contentPane;728}729730/**731* Create a frame for SwingSet2 to reside in if brought up732* as an application.733*/734public static JFrame createFrame(GraphicsConfiguration gc) {735JFrame frame = new JFrame(gc);736if (numSSs == 0) {737frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);738} else {739WindowListener l = new WindowAdapter() {740public void windowClosing(WindowEvent e) {741numSSs--;742swingSets.remove(this);743}744};745frame.addWindowListener(l);746}747return frame;748}749750751/**752* Set the status753*/754public void setStatus(String s) {755// do the following on the gui thread756SwingUtilities.invokeLater(new SwingSetRunnable(this, s) {757public void run() {758swingset.statusField.setText((String) obj);759}760});761}762763764/**765* This method returns a string from the demo's resource bundle.766*/767public static String getString(String key) {768String value = null;769try {770value = TextAndMnemonicUtils.getTextAndMnemonicString(key);771} catch (MissingResourceException e) {772System.out.println("java.util.MissingResourceException: Couldn't find value for: " + key);773}774if(value == null) {775value = "Could not find resource: " + key + " ";776}777return value;778}779780void setDragEnabled(boolean dragEnabled) {781if (dragEnabled == this.dragEnabled) {782return;783}784785this.dragEnabled = dragEnabled;786787for (DemoModule dm : demosList) {788dm.updateDragEnabled(dragEnabled);789}790791demoSrcPane.setDragEnabled(dragEnabled);792}793794boolean isDragEnabled() {795return dragEnabled;796}797798799/**800* Returns a mnemonic from the resource bundle. Typically used as801* keyboard shortcuts in menu items.802*/803public char getMnemonic(String key) {804return (getString(key)).charAt(0);805}806807/**808* Creates an icon from an image contained in the "images" directory.809*/810public ImageIcon createImageIcon(String filename, String description) {811String path = "/resources/images/" + filename;812return new ImageIcon(getClass().getResource(path));813}814815/**816* If DEBUG is defined, prints debug information out to std ouput.817*/818public void debug(String s) {819if(DEBUG) {820System.out.println((debugCounter++) + ": " + s);821}822}823824/**825* Stores the current L&F, and calls updateLookAndFeel, below826*/827public void setLookAndFeel(LookAndFeelData laf) {828if(!currentLookAndFeel.equals(laf)) {829currentLookAndFeel = laf;830/* The recommended way of synchronizing state between multiple831* controls that represent the same command is to use Actions.832* The code below is a workaround and will be replaced in future833* version of SwingSet2 demo.834*/835String lafName = laf.label;836themesMenu.setEnabled(laf.name.equals("Metal"));837updateLookAndFeel();838for(int i=0;i<lafMenu.getItemCount();i++) {839JMenuItem item = lafMenu.getItem(i);840item.setSelected(item.getText().equals(lafName));841}842}843}844845private void updateThisSwingSet() {846JFrame frame = getFrame();847if (frame == null) {848SwingUtilities.updateComponentTreeUI(this);849} else {850SwingUtilities.updateComponentTreeUI(frame);851}852853SwingUtilities.updateComponentTreeUI(popupMenu);854if (aboutBox != null) {855SwingUtilities.updateComponentTreeUI(aboutBox);856}857}858859/**860* Sets the current L&F on each demo module861*/862public void updateLookAndFeel() {863try {864UIManager.setLookAndFeel(currentLookAndFeel.className);865for (SwingSet2 ss : swingSets) {866ss.updateThisSwingSet();867}868} catch (Exception ex) {869System.out.println("Failed loading L&F: " + currentLookAndFeel);870System.out.println(ex);871}872}873874/**875* Loads and puts the source code text into JEditorPane in the "Source Code" tab876*/877public void setSourceCode(DemoModule demo) {878// do the following on the gui thread879SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {880public void run() {881swingset.demoSrcPane.setText(((DemoModule)obj).getSourceCode());882swingset.demoSrcPane.setCaretPosition(0);883884}885});886}887888// *******************************************************889// ************** ToggleButtonToolbar *****************890// *******************************************************891static Insets zeroInsets = new Insets(1,1,1,1);892protected class ToggleButtonToolBar extends JToolBar {893public ToggleButtonToolBar() {894super();895}896897JToggleButton addToggleButton(Action a) {898JToggleButton tb = new JToggleButton(899(String)a.getValue(Action.NAME),900(Icon)a.getValue(Action.SMALL_ICON)901);902tb.setMargin(zeroInsets);903tb.setText(null);904tb.setEnabled(a.isEnabled());905tb.setToolTipText((String)a.getValue(Action.SHORT_DESCRIPTION));906tb.setAction(a);907add(tb);908return tb;909}910}911912// *******************************************************913// ********* ToolBar Panel / Docking Listener ***********914// *******************************************************915class ToolBarPanel extends JPanel implements ContainerListener {916917public boolean contains(int x, int y) {918Component c = getParent();919if (c != null) {920Rectangle r = c.getBounds();921return (x >= 0) && (x < r.width) && (y >= 0) && (y < r.height);922}923else {924return super.contains(x,y);925}926}927928public void componentAdded(ContainerEvent e) {929Container c = e.getContainer().getParent();930if (c != null) {931c.getParent().validate();932c.getParent().repaint();933}934}935936public void componentRemoved(ContainerEvent e) {937Container c = e.getContainer().getParent();938if (c != null) {939c.getParent().validate();940c.getParent().repaint();941}942}943}944945// *******************************************************946// ****************** Runnables ***********************947// *******************************************************948949/**950* Generic SwingSet2 runnable. This is intended to run on the951* AWT gui event thread so as not to muck things up by doing952* gui work off the gui thread. Accepts a SwingSet2 and an Object953* as arguments, which gives subtypes of this class the two954* "must haves" needed in most runnables for this demo.955*/956class SwingSetRunnable implements Runnable {957protected SwingSet2 swingset;958protected Object obj;959960public SwingSetRunnable(SwingSet2 swingset, Object obj) {961this.swingset = swingset;962this.obj = obj;963}964965public void run() {966}967}968969970// *******************************************************971// ******************** Actions ***********************972// *******************************************************973974public class SwitchToDemoAction extends AbstractAction {975SwingSet2 swingset;976DemoModule demo;977978public SwitchToDemoAction(SwingSet2 swingset, DemoModule demo) {979super(demo.getName(), demo.getIcon());980this.swingset = swingset;981this.demo = demo;982}983984public void actionPerformed(ActionEvent e) {985swingset.setDemo(demo);986}987}988989class OkAction extends AbstractAction {990JDialog aboutBox;991992protected OkAction(JDialog aboutBox) {993super("OkAction");994this.aboutBox = aboutBox;995}996997public void actionPerformed(ActionEvent e) {998aboutBox.setVisible(false);999}1000}10011002class ChangeLookAndFeelAction extends AbstractAction {1003SwingSet2 swingset;1004LookAndFeelData lafData;1005protected ChangeLookAndFeelAction(SwingSet2 swingset, LookAndFeelData lafData) {1006super("ChangeTheme");1007this.swingset = swingset;1008this.lafData = lafData;1009}10101011public void actionPerformed(ActionEvent e) {1012swingset.setLookAndFeel(lafData);1013}1014}10151016class ActivatePopupMenuAction extends AbstractAction {1017SwingSet2 swingset;1018JPopupMenu popup;1019protected ActivatePopupMenuAction(SwingSet2 swingset, JPopupMenu popup) {1020super("ActivatePopupMenu");1021this.swingset = swingset;1022this.popup = popup;1023}10241025public void actionPerformed(ActionEvent e) {1026Dimension invokerSize = getSize();1027Dimension popupSize = popup.getPreferredSize();1028popup.show(swingset, (invokerSize.width - popupSize.width) / 2,1029(invokerSize.height - popupSize.height) / 2);1030}1031}10321033// Turns on all possible auditory feedback1034class OnAudioAction extends AbstractAction {1035SwingSet2 swingset;1036protected OnAudioAction(SwingSet2 swingset) {1037super("Audio On");1038this.swingset = swingset;1039}1040public void actionPerformed(ActionEvent e) {1041UIManager.put("AuditoryCues.playList",1042UIManager.get("AuditoryCues.allAuditoryCues"));1043swingset.updateLookAndFeel();1044}1045}10461047// Turns on the default amount of auditory feedback1048class DefaultAudioAction extends AbstractAction {1049SwingSet2 swingset;1050protected DefaultAudioAction(SwingSet2 swingset) {1051super("Audio Default");1052this.swingset = swingset;1053}1054public void actionPerformed(ActionEvent e) {1055UIManager.put("AuditoryCues.playList",1056UIManager.get("AuditoryCues.defaultCueList"));1057swingset.updateLookAndFeel();1058}1059}10601061// Turns off all possible auditory feedback1062class OffAudioAction extends AbstractAction {1063SwingSet2 swingset;1064protected OffAudioAction(SwingSet2 swingset) {1065super("Audio Off");1066this.swingset = swingset;1067}1068public void actionPerformed(ActionEvent e) {1069UIManager.put("AuditoryCues.playList",1070UIManager.get("AuditoryCues.noAuditoryCues"));1071swingset.updateLookAndFeel();1072}1073}10741075// Turns on or off the tool tips for the demo.1076class ToolTipAction extends AbstractAction {1077protected ToolTipAction() {1078super("ToolTip Control");1079}10801081public void actionPerformed(ActionEvent e) {1082boolean status = ((JCheckBoxMenuItem)e.getSource()).isSelected();1083ToolTipManager.sharedInstance().setEnabled(status);1084}1085}10861087class DragSupportAction extends AbstractAction {1088protected DragSupportAction() {1089super("DragSupport Control");1090}10911092public void actionPerformed(ActionEvent e) {1093boolean dragEnabled = ((JCheckBoxMenuItem)e.getSource()).isSelected();1094for (SwingSet2 ss : swingSets) {1095ss.setDragEnabled(dragEnabled);1096}1097}1098}10991100class ChangeThemeAction extends AbstractAction {1101SwingSet2 swingset;1102MetalTheme theme;1103protected ChangeThemeAction(SwingSet2 swingset, MetalTheme theme) {1104super("ChangeTheme");1105this.swingset = swingset;1106this.theme = theme;1107}11081109public void actionPerformed(ActionEvent e) {1110MetalLookAndFeel.setCurrentTheme(theme);1111swingset.updateLookAndFeel();1112}1113}11141115class ExitAction extends AbstractAction {1116SwingSet2 swingset;1117protected ExitAction(SwingSet2 swingset) {1118super("ExitAction");1119this.swingset = swingset;1120}11211122public void actionPerformed(ActionEvent e) {1123System.exit(0);1124}1125}11261127class AboutAction extends AbstractAction {1128SwingSet2 swingset;1129protected AboutAction(SwingSet2 swingset) {1130super("AboutAction");1131this.swingset = swingset;1132}11331134public void actionPerformed(ActionEvent e) {1135if(aboutBox == null) {1136// JPanel panel = new JPanel(new BorderLayout());1137JPanel panel = new AboutPanel(swingset);1138panel.setLayout(new BorderLayout());11391140aboutBox = new JDialog(swingset.getFrame(), getString("AboutBox.title"), false);1141aboutBox.setResizable(false);1142aboutBox.getContentPane().add(panel, BorderLayout.CENTER);11431144// JButton button = new JButton(getString("AboutBox.ok_button_text"));1145JPanel buttonpanel = new JPanel();1146buttonpanel.setBorder(new javax.swing.border.EmptyBorder(0, 0, 3, 0));1147buttonpanel.setOpaque(false);1148JButton button = (JButton) buttonpanel.add(1149new JButton(getString("AboutBox.ok_button_text"))1150);1151panel.add(buttonpanel, BorderLayout.SOUTH);11521153button.addActionListener(new OkAction(aboutBox));1154}1155aboutBox.pack();1156aboutBox.setLocationRelativeTo(getFrame());1157aboutBox.setVisible(true);1158}1159}11601161class MultiScreenAction extends AbstractAction {1162static final int ALL_SCREENS = -1;1163int screen;1164protected MultiScreenAction(SwingSet2 swingset, int screen) {1165super("MultiScreenAction");1166this.screen = screen;1167}11681169public void actionPerformed(ActionEvent e) {1170GraphicsDevice[] gds = GraphicsEnvironment.1171getLocalGraphicsEnvironment().1172getScreenDevices();1173if (screen == ALL_SCREENS) {1174for (int i = 0; i < gds.length; i++) {1175SwingSet2 swingset = new SwingSet2(1176gds[i].getDefaultConfiguration());1177swingset.setDragEnabled(dragEnabled);1178}1179}1180else {1181SwingSet2 swingset = new SwingSet2(1182gds[screen].getDefaultConfiguration());1183swingset.setDragEnabled(dragEnabled);1184}1185}1186}11871188// *******************************************************1189// ********************** Misc *************************1190// *******************************************************11911192class DemoLoadThread extends Thread {1193SwingSet2 swingset;11941195DemoLoadThread(SwingSet2 swingset) {1196this.swingset = swingset;1197}11981199public void run() {1200SwingUtilities.invokeLater(swingset::loadDemos);1201}1202}12031204class AboutPanel extends JPanel {1205ImageIcon aboutimage = null;1206SwingSet2 swingset = null;12071208public AboutPanel(SwingSet2 swingset) {1209this.swingset = swingset;1210aboutimage = swingset.createImageIcon("About.jpg", "AboutBox.accessible_description");1211setOpaque(false);1212}12131214public void paint(Graphics g) {1215aboutimage.paintIcon(this, g, 0, 0);1216super.paint(g);1217}12181219public Dimension getPreferredSize() {1220return new Dimension(aboutimage.getIconWidth(),1221aboutimage.getIconHeight());1222}1223}122412251226private class ChangeFontAction extends AbstractAction {1227private SwingSet2 swingset;1228private boolean plain;12291230ChangeFontAction(SwingSet2 swingset, boolean plain) {1231super("FontMenu");1232this.swingset = swingset;1233this.plain = plain;1234}12351236public void actionPerformed(ActionEvent e) {1237if (plain) {1238UIManager.put("swing.boldMetal", Boolean.FALSE);1239}1240else {1241UIManager.put("swing.boldMetal", Boolean.TRUE);1242}1243// Change the look and feel to force the settings to take effect.1244updateLookAndFeel();1245}1246}12471248private static LookAndFeelData[] getInstalledLookAndFeelData() {1249return Arrays.stream(UIManager.getInstalledLookAndFeels())1250.map(laf -> getLookAndFeelData(laf))1251.toArray(LookAndFeelData[]::new);1252}12531254private static LookAndFeelData getLookAndFeelData(1255UIManager.LookAndFeelInfo info) {1256switch (info.getName()) {1257case "Metal":1258return new LookAndFeelData(info, "java");1259case "Nimbus":1260return new LookAndFeelData(info, "nimbus");1261case "Windows":1262return new LookAndFeelData(info, "windows");1263case "GTK+":1264return new LookAndFeelData(info, "gtk");1265case "CDE/Motif":1266return new LookAndFeelData(info, "motif");1267case "Mac OS X":1268return new LookAndFeelData(info, "mac");1269default:1270return new LookAndFeelData(info);1271}1272}12731274private static class LookAndFeelData {1275String name;1276String className;1277String label;1278char mnemonic;1279String accDescription;12801281public LookAndFeelData(UIManager.LookAndFeelInfo info) {1282this(info.getName(), info.getClassName(), info.getName(),1283info.getName(), info.getName());1284}12851286public LookAndFeelData(UIManager.LookAndFeelInfo info, String property) {1287this(info.getName(), info.getClassName(),1288getString(String.format("LafMenu.%s_label", property)),1289getString(String.format("LafMenu.%s_mnemonic", property)),1290getString(String.format("LafMenu.%s_accessible_description",1291property)));1292}12931294public LookAndFeelData(String name, String className, String label,1295String mnemonic, String accDescription) {1296this.name = name;1297this.className = className;1298this.label = label;1299this.mnemonic = mnemonic.charAt(0);1300this.accDescription = accDescription;1301}13021303@Override1304public String toString() {1305return className;1306}1307}1308}130913101311