Path: blob/master/test/jdk/sanity/client/lib/SwingSet2/src/SwingSet2.java
41161 views
/*1* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.awt.BorderLayout;24import java.awt.Component;25import java.awt.Container;26import java.awt.Dimension;27import java.awt.Graphics;28import java.awt.GraphicsConfiguration;29import java.awt.GraphicsDevice;30import java.awt.GraphicsEnvironment;31import java.awt.Insets;32import java.awt.Rectangle;33import java.awt.Toolkit;34import java.awt.event.ActionEvent;35import java.awt.event.ContainerEvent;36import java.awt.event.ContainerListener;37import java.awt.event.InputEvent;38import java.awt.event.KeyEvent;39import java.awt.event.WindowAdapter;40import java.awt.event.WindowEvent;41import java.awt.event.WindowListener;42import java.util.ArrayList;43import java.util.Arrays;44import java.util.MissingResourceException;45import java.util.Vector;4647import javax.swing.AbstractAction;48import javax.swing.Action;49import javax.swing.ButtonGroup;50import javax.swing.Icon;51import javax.swing.ImageIcon;52import javax.swing.InputMap;53import javax.swing.JButton;54import javax.swing.JCheckBoxMenuItem;55import javax.swing.JComponent;56import javax.swing.JDialog;57import javax.swing.JEditorPane;58import javax.swing.JFrame;59import javax.swing.JMenu;60import javax.swing.JMenuBar;61import javax.swing.JMenuItem;62import javax.swing.JPanel;63import javax.swing.JPopupMenu;64import javax.swing.JRadioButtonMenuItem;65import javax.swing.JScrollPane;66import javax.swing.JTabbedPane;67import javax.swing.JTextField;68import javax.swing.JToggleButton;69import javax.swing.JToolBar;70import javax.swing.KeyStroke;71import javax.swing.SingleSelectionModel;72import javax.swing.SwingUtilities;73import javax.swing.ToolTipManager;74import javax.swing.UIManager;75import javax.swing.border.EtchedBorder;76import javax.swing.event.ChangeEvent;77import javax.swing.event.ChangeListener;78import javax.swing.plaf.metal.DefaultMetalTheme;79import javax.swing.plaf.metal.MetalLookAndFeel;80import javax.swing.plaf.metal.MetalTheme;81import javax.swing.plaf.metal.OceanTheme;8283/**84* A demo that shows all of the Swing components.85*86* @author Jeff Dinkins87*/88public class SwingSet2 extends JPanel {8990String[] demos = {91"ButtonDemo",92"ColorChooserDemo",93"ComboBoxDemo",94"FileChooserDemo",95"HtmlDemo",96"ListDemo",97"OptionPaneDemo",98"ProgressBarDemo",99"ScrollPaneDemo",100"SliderDemo",101"SplitPaneDemo",102"TabbedPaneDemo",103"TableDemo",104"ToolTipDemo",105"TreeDemo"106};107108// The current Look & Feel109private static LookAndFeelData currentLookAndFeel;110private static LookAndFeelData[] lookAndFeelData;111// List of demos112private ArrayList<DemoModule> demosList = new ArrayList<DemoModule>();113114public static final String FRAME_TITLE = getString("Frame.title");115public static final String THEMES_MENU_TEXT = getString("ThemesMenu.themes_label");116public static final String OPTIONS_MENU_TEXT = getString("OptionsMenu.options_label");117public static final String FONT_MENU_TEXT = getString("FontMenu.fonts_label");118public static final String FONT_PLAIN_MENU_TEXT = getString("FontMenu.plain_label");119public static final String FONT_BOLD_MENU_TEXT = getString("FontMenu.bold_label");120public static final String TOOLTIP_MENU_TEXT = getString("OptionsMenu.tooltip_label");121public static final String OCEAN_MENU_TEXT = getString("ThemesMenu.ocean_label");122public static final String AQUA_MENU_TEXT = getString("ThemesMenu.aqua_label");123public static final String STEEL_MENU_TEXT = getString("ThemesMenu.steel_label");124public static final String CONTRAST_MENU_TEXT = getString("ThemesMenu.contrast_label");125public static final String CHARCOAL_MENU_TEXT = getString("ThemesMenu.charcoal_label");126public static final String EMERALD_MENU_TEXT = getString("ThemesMenu.emerald_label");127public static final String RUBY_MENU_TEXT= getString("ThemesMenu.ruby_label");128public static final String NAME_PROP_SUFFIX = ".name";129130// The preferred size of the demo131private static final int PREFERRED_WIDTH = 720;132private static final int PREFERRED_HEIGHT = 640;133134// A place to hold on to the visible demo135private DemoModule currentDemo = null;136private JPanel demoPanel = null;137138// About Box139private JDialog aboutBox = null;140141// Status Bar142private JTextField statusField = null;143144// Tool Bar145private ToggleButtonToolBar toolbar = null;146private ButtonGroup toolbarGroup = new ButtonGroup();147148// Menus149private JMenuBar menuBar = null;150private JMenu lafMenu = null;151private JMenu themesMenu = null;152private JMenu audioMenu = null;153private JMenu optionsMenu = null;154private ButtonGroup lafMenuGroup = new ButtonGroup();155private ButtonGroup themesMenuGroup = new ButtonGroup();156private ButtonGroup audioMenuGroup = new ButtonGroup();157158// Popup menu159private JPopupMenu popupMenu = null;160private ButtonGroup popupMenuGroup = new ButtonGroup();161162// Used only if swingset is an application163private JFrame frame = null;164165// The tab pane that holds the demo166private JTabbedPane tabbedPane = null;167168private JEditorPane demoSrcPane = null;169170171// contentPane cache, saved from the application frame172Container contentPane = null;173174175// number of swingsets - for multiscreen176// keep track of the number of SwingSets created - we only want to exit177// the program when the last one has been closed.178private static int numSSs = 0;179private static Vector<SwingSet2> swingSets = new Vector<SwingSet2>();180181private boolean dragEnabled = false;182183/**184* SwingSet2 Constructor185*/186public SwingSet2(GraphicsConfiguration gc) {187188String lafClassName = UIManager.getLookAndFeel().getClass().getName();189lookAndFeelData = getInstalledLookAndFeelData();190currentLookAndFeel = Arrays.stream(lookAndFeelData)191.filter(laf -> lafClassName.equals(laf.className))192.findFirst().get();193194frame = createFrame(gc);195196// set the layout197setLayout(new BorderLayout());198199// set the preferred size of the demo200setPreferredSize(new Dimension(PREFERRED_WIDTH,PREFERRED_HEIGHT));201202initializeDemo();203preloadFirstDemo();204205showSwingSet2();206}207208/**209* SwingSet2 Main.210*/211public static void main(final String[] args) {212// must run in EDT when constructing the GUI components213SwingUtilities.invokeLater(() -> {214// Create SwingSet on the default monitor215UIManager.put("swing.boldMetal", Boolean.FALSE);216SwingSet2 swingset = new SwingSet2(GraphicsEnvironment.217getLocalGraphicsEnvironment().218getDefaultScreenDevice().219getDefaultConfiguration());220});221}222223// *******************************************************224// *************** Demo Loading Methods ******************225// *******************************************************226227228public void initializeDemo() {229JPanel top = new JPanel();230top.setLayout(new BorderLayout());231add(top, BorderLayout.NORTH);232233menuBar = createMenus();234frame.setJMenuBar(menuBar);235236// creates popup menu accessible via keyboard237popupMenu = createPopupMenu();238239ToolBarPanel toolbarPanel = new ToolBarPanel();240toolbarPanel.setLayout(new BorderLayout());241toolbar = new ToggleButtonToolBar();242toolbarPanel.add(toolbar, BorderLayout.CENTER);243top.add(toolbarPanel, BorderLayout.SOUTH);244toolbarPanel.addContainerListener(toolbarPanel);245246tabbedPane = new JTabbedPane();247add(tabbedPane, BorderLayout.CENTER);248tabbedPane.getModel().addChangeListener(new TabListener());249250statusField = new JTextField("");251statusField.setEditable(false);252add(statusField, BorderLayout.SOUTH);253254demoPanel = new JPanel();255demoPanel.setLayout(new BorderLayout());256demoPanel.setBorder(new EtchedBorder());257tabbedPane.addTab("Hi There!", demoPanel);258259// Add html src code viewer260demoSrcPane = new JEditorPane("text/html", getString("SourceCode.loading"));261demoSrcPane.setEditable(false);262263JScrollPane scroller = new JScrollPane();264scroller.getViewport().add(demoSrcPane);265266tabbedPane.addTab(267getString("TabbedPane.src_label"),268null,269scroller,270getString("TabbedPane.src_tooltip")271);272}273274DemoModule currentTabDemo = null;275class TabListener implements ChangeListener {276public void stateChanged(ChangeEvent e) {277SingleSelectionModel model = (SingleSelectionModel) e.getSource();278boolean srcSelected = model.getSelectedIndex() == 1;279if(currentTabDemo != currentDemo && demoSrcPane != null && srcSelected) {280demoSrcPane.setText(getString("SourceCode.loading"));281repaint();282}283if(currentTabDemo != currentDemo && srcSelected) {284currentTabDemo = currentDemo;285setSourceCode(currentDemo);286}287}288}289290/**291* Create menus292*/293public JMenuBar createMenus() {294JMenuItem mi;295// ***** create the menubar ****296JMenuBar menuBar = new JMenuBar();297menuBar.getAccessibleContext().setAccessibleName(298getString("MenuBar.accessible_description"));299300// ***** create File menu301JMenu fileMenu = (JMenu) menuBar.add(new JMenu(getString("FileMenu.file_label")));302fileMenu.setMnemonic(getMnemonic("FileMenu.file_mnemonic"));303fileMenu.getAccessibleContext().setAccessibleDescription(getString("FileMenu.accessible_description"));304305createMenuItem(fileMenu, "FileMenu.about_label", "FileMenu.about_mnemonic",306"FileMenu.about_accessible_description", new AboutAction(this));307308fileMenu.addSeparator();309310createMenuItem(fileMenu, "FileMenu.open_label", "FileMenu.open_mnemonic",311"FileMenu.open_accessible_description", null);312313createMenuItem(fileMenu, "FileMenu.save_label", "FileMenu.save_mnemonic",314"FileMenu.save_accessible_description", null);315316createMenuItem(fileMenu, "FileMenu.save_as_label", "FileMenu.save_as_mnemonic",317"FileMenu.save_as_accessible_description", null);318319fileMenu.addSeparator();320321createMenuItem(fileMenu, "FileMenu.exit_label", "FileMenu.exit_mnemonic",322"FileMenu.exit_accessible_description", new ExitAction(this)323);324325// ***** create laf switcher menu326lafMenu = (JMenu) menuBar.add(new JMenu(getString("LafMenu.laf_label")));327lafMenu.setMnemonic(getMnemonic("LafMenu.laf_mnemonic"));328lafMenu.getAccessibleContext().setAccessibleDescription(329getString("LafMenu.laf_accessible_description"));330331for (LookAndFeelData lafData : lookAndFeelData) {332mi = createLafMenuItem(lafMenu, lafData);333mi.setSelected(lafData.equals(currentLookAndFeel));334}335336// ***** create themes menu337themesMenu = (JMenu) menuBar.add(new JMenu(THEMES_MENU_TEXT));338themesMenu.setMnemonic(getMnemonic("ThemesMenu.themes_mnemonic"));339themesMenu.getAccessibleContext().setAccessibleDescription(340getString("ThemesMenu.themes_accessible_description"));341342// ***** create the audio submenu under the theme menu343audioMenu = (JMenu) themesMenu.add(new JMenu(getString("AudioMenu.audio_label")));344audioMenu.setMnemonic(getMnemonic("AudioMenu.audio_mnemonic"));345audioMenu.getAccessibleContext().setAccessibleDescription(346getString("AudioMenu.audio_accessible_description"));347348createAudioMenuItem(audioMenu, "AudioMenu.on_label",349"AudioMenu.on_mnemonic",350"AudioMenu.on_accessible_description",351new OnAudioAction(this));352353mi = createAudioMenuItem(audioMenu, "AudioMenu.default_label",354"AudioMenu.default_mnemonic",355"AudioMenu.default_accessible_description",356new DefaultAudioAction(this));357mi.setSelected(true); // This is the default feedback setting358359createAudioMenuItem(audioMenu, "AudioMenu.off_label",360"AudioMenu.off_mnemonic",361"AudioMenu.off_accessible_description",362new OffAudioAction(this));363364365// ***** create the font submenu under the theme menu366JMenu fontMenu = (JMenu) themesMenu.add(new JMenu(FONT_MENU_TEXT));367fontMenu.setMnemonic(getMnemonic("FontMenu.fonts_mnemonic"));368fontMenu.getAccessibleContext().setAccessibleDescription(369getString("FontMenu.fonts_accessible_description"));370ButtonGroup fontButtonGroup = new ButtonGroup();371mi = createButtonGroupMenuItem(fontMenu, FONT_PLAIN_MENU_TEXT,372"FontMenu.plain_mnemonic",373"FontMenu.plain_accessible_description",374new ChangeFontAction(this, true), fontButtonGroup);375mi.setSelected(true);376mi = createButtonGroupMenuItem(fontMenu, FONT_BOLD_MENU_TEXT,377"FontMenu.bold_mnemonic",378"FontMenu.bold_accessible_description",379new ChangeFontAction(this, false), fontButtonGroup);380381382383// *** now back to adding color/font themes to the theme menu384mi = createThemesMenuItem(themesMenu, OCEAN_MENU_TEXT,385"ThemesMenu.ocean_mnemonic",386"ThemesMenu.ocean_accessible_description",387new OceanTheme());388mi.setSelected(true); // This is the default theme389390createThemesMenuItem(themesMenu, STEEL_MENU_TEXT,391"ThemesMenu.steel_mnemonic",392"ThemesMenu.steel_accessible_description",393new DefaultMetalTheme());394395createThemesMenuItem(themesMenu, AQUA_MENU_TEXT, "ThemesMenu.aqua_mnemonic",396"ThemesMenu.aqua_accessible_description", new AquaTheme());397398createThemesMenuItem(themesMenu, CHARCOAL_MENU_TEXT, "ThemesMenu.charcoal_mnemonic",399"ThemesMenu.charcoal_accessible_description", new CharcoalTheme());400401createThemesMenuItem(themesMenu, CONTRAST_MENU_TEXT, "ThemesMenu.contrast_mnemonic",402"ThemesMenu.contrast_accessible_description", new ContrastTheme());403404createThemesMenuItem(themesMenu, EMERALD_MENU_TEXT, "ThemesMenu.emerald_mnemonic",405"ThemesMenu.emerald_accessible_description", new EmeraldTheme());406407createThemesMenuItem(themesMenu, RUBY_MENU_TEXT, "ThemesMenu.ruby_mnemonic",408"ThemesMenu.ruby_accessible_description", new RubyTheme());409410// Enable theme menu based on L&F411themesMenu.setEnabled("Metal".equals(currentLookAndFeel.name));412413// ***** create the options menu414optionsMenu = (JMenu)menuBar.add(415new JMenu(OPTIONS_MENU_TEXT));416optionsMenu.setMnemonic(getMnemonic("OptionsMenu.options_mnemonic"));417optionsMenu.getAccessibleContext().setAccessibleDescription(418getString("OptionsMenu.options_accessible_description"));419420// ***** create tool tip submenu item.421mi = createCheckBoxMenuItem(optionsMenu, TOOLTIP_MENU_TEXT,422"OptionsMenu.tooltip_mnemonic",423"OptionsMenu.tooltip_accessible_description",424new ToolTipAction());425mi.setSelected(true);426427// ***** create drag support submenu item.428createCheckBoxMenuItem(optionsMenu, getString("OptionsMenu.dragEnabled_label"),429"OptionsMenu.dragEnabled_mnemonic",430"OptionsMenu.dragEnabled_accessible_description",431new DragSupportAction());432433// ***** create the multiscreen menu, if we have multiple screens434GraphicsDevice[] screens = GraphicsEnvironment.435getLocalGraphicsEnvironment().436getScreenDevices();437if (screens.length > 1) {438JMenu multiScreenMenu = (JMenu) menuBar.add(new JMenu(439getString("MultiMenu.multi_label")));440multiScreenMenu.setMnemonic(getMnemonic("MultiMenu.multi_mnemonic"));441multiScreenMenu.getAccessibleContext().setAccessibleDescription(442getString("MultiMenu.multi_accessible_description"));443444createMultiscreenMenuItem(multiScreenMenu, MultiScreenAction.ALL_SCREENS);445for (int i = 0; i < screens.length; i++) {446createMultiscreenMenuItem(multiScreenMenu, i);447}448}449return menuBar;450}451452/**453* Create a checkbox menu menu item454*/455private JMenuItem createCheckBoxMenuItem(JMenu menu, String label,456String mnemonic,457String accessibleDescription,458Action action) {459JCheckBoxMenuItem mi = (JCheckBoxMenuItem)menu.add(460new JCheckBoxMenuItem(label));461mi.setMnemonic(getMnemonic(mnemonic));462mi.getAccessibleContext().setAccessibleDescription(getString(463accessibleDescription));464mi.addActionListener(action);465return mi;466}467468/**469* Create a radio button menu menu item for items that are part of a470* button group.471*/472private JMenuItem createButtonGroupMenuItem(JMenu menu, String label,473String mnemonic,474String accessibleDescription,475Action action,476ButtonGroup buttonGroup) {477JRadioButtonMenuItem mi = (JRadioButtonMenuItem)menu.add(478new JRadioButtonMenuItem(label));479buttonGroup.add(mi);480mi.setMnemonic(getMnemonic(mnemonic));481mi.getAccessibleContext().setAccessibleDescription(getString(482accessibleDescription));483mi.addActionListener(action);484return mi;485}486487/**488* Create the theme's audio submenu489*/490public JMenuItem createAudioMenuItem(JMenu menu, String label,491String mnemonic,492String accessibleDescription,493Action action) {494JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(getString(label)));495audioMenuGroup.add(mi);496mi.setMnemonic(getMnemonic(mnemonic));497mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));498mi.addActionListener(action);499return mi;500}501502/**503* Creates a generic menu item504*/505public JMenuItem createMenuItem(JMenu menu, String label, String mnemonic,506String accessibleDescription, Action action) {507JMenuItem mi = (JMenuItem) menu.add(new JMenuItem(getString(label)));508mi.setMnemonic(getMnemonic(mnemonic));509mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));510mi.addActionListener(action);511if(action == null) {512mi.setEnabled(false);513}514return mi;515}516517/**518* Creates a JRadioButtonMenuItem for the Themes menu519*/520public JMenuItem createThemesMenuItem(JMenu menu, String label, String mnemonic,521String accessibleDescription, MetalTheme theme) {522JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu.add(new JRadioButtonMenuItem(label));523themesMenuGroup.add(mi);524mi.setMnemonic(getMnemonic(mnemonic));525mi.getAccessibleContext().setAccessibleDescription(getString(accessibleDescription));526mi.addActionListener(new ChangeThemeAction(this, theme));527return mi;528}529530/**531* Creates a JRadioButtonMenuItem for the Look and Feel menu532*/533public JMenuItem createLafMenuItem(JMenu menu, LookAndFeelData lafData) {534JMenuItem mi = menu.add(new JRadioButtonMenuItem(lafData.label));535lafMenuGroup.add(mi);536mi.setMnemonic(lafData.mnemonic);537mi.getAccessibleContext().setAccessibleDescription(lafData.accDescription);538mi.addActionListener(new ChangeLookAndFeelAction(this, lafData));539return mi;540}541542/**543* Creates a multi-screen menu item544*/545public JMenuItem createMultiscreenMenuItem(JMenu menu, int screen) {546JMenuItem mi = null;547if (screen == MultiScreenAction.ALL_SCREENS) {548mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.all_label")));549mi.setMnemonic(getMnemonic("MultiMenu.all_mnemonic"));550mi.getAccessibleContext().setAccessibleDescription(getString(551"MultiMenu.all_accessible_description"));552}553else {554mi = (JMenuItem) menu.add(new JMenuItem(getString("MultiMenu.single_label") + " " +555screen));556mi.setMnemonic(KeyEvent.VK_0 + screen);557mi.getAccessibleContext().setAccessibleDescription(getString(558"MultiMenu.single_accessible_description") + " " + screen);559560}561mi.addActionListener(new MultiScreenAction(this, screen));562return mi;563}564565public JPopupMenu createPopupMenu() {566JPopupMenu popup = new JPopupMenu("JPopupMenu demo");567568for (LookAndFeelData lafData : lookAndFeelData) {569createPopupMenuItem(popup, lafData);570}571572// register key binding to activate popup menu573InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);574map.put(KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.SHIFT_MASK),575"postMenuAction");576map.put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTEXT_MENU, 0), "postMenuAction");577getActionMap().put("postMenuAction", new ActivatePopupMenuAction(this, popup));578579return popup;580}581582/**583* Creates a JMenuItem for the Look and Feel popup menu584*/585public JMenuItem createPopupMenuItem(JPopupMenu menu, LookAndFeelData lafData) {586JMenuItem mi = menu.add(new JMenuItem(lafData.label));587popupMenuGroup.add(mi);588mi.setMnemonic(lafData.mnemonic);589mi.getAccessibleContext().setAccessibleDescription(lafData.accDescription);590mi.addActionListener(new ChangeLookAndFeelAction(this, lafData));591return mi;592}593594/**595* Load the first demo. This is done separately from the remaining demos596* so that we can get SwingSet2 up and available to the user quickly.597*/598public void preloadFirstDemo() {599DemoModule demo = addDemo(new OptionPaneDemo(this));600setDemo(demo);601}602603/**604* Add a demo to the toolbar605*/606public DemoModule addDemo(DemoModule demo) {607demosList.add(demo);608if (dragEnabled) {609demo.updateDragEnabled(true);610}611// do the following on the gui thread612SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {613public void run() {614SwitchToDemoAction action = new SwitchToDemoAction(swingset, (DemoModule) obj);615JToggleButton tb = swingset.getToolBar().addToggleButton(action);616swingset.getToolBarGroup().add(tb);617if(swingset.getToolBarGroup().getSelection() == null) {618tb.setSelected(true);619}620tb.setText(null);621tb.setToolTipText(((DemoModule)obj).getToolTip());622623if(demos[demos.length-1].equals(obj.getClass().getName())) {624setStatus(getString("Status.popupMenuAccessible"));625}626}627});628return demo;629}630631/**632* Sets the current demo633*/634public void setDemo(DemoModule demo) {635currentDemo = demo;636637// Ensure panel's UI is current before making visible638JComponent currentDemoPanel = demo.getDemoPanel();639SwingUtilities.updateComponentTreeUI(currentDemoPanel);640641demoPanel.removeAll();642demoPanel.add(currentDemoPanel, BorderLayout.CENTER);643644tabbedPane.setSelectedIndex(0);645tabbedPane.setTitleAt(0, demo.getName());646tabbedPane.setToolTipTextAt(0, demo.getToolTip());647}648649/**650* Bring up the SwingSet2 demo by showing the frame651*/652public void showSwingSet2() {653if(getFrame() != null) {654// put swingset in a frame and show it655JFrame f = getFrame();656f.setTitle(FRAME_TITLE);657f.getContentPane().add(this, BorderLayout.CENTER);658f.pack();659660Rectangle screenRect = f.getGraphicsConfiguration().getBounds();661Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(662f.getGraphicsConfiguration());663664// Make sure we don't place the demo off the screen.665int centerWidth = screenRect.width < f.getSize().width ?666screenRect.x :667screenRect.x + screenRect.width/2 - f.getSize().width/2;668int centerHeight = screenRect.height < f.getSize().height ?669screenRect.y :670screenRect.y + screenRect.height/2 - f.getSize().height/2;671672centerHeight = centerHeight < screenInsets.top ?673screenInsets.top : centerHeight;674675f.setLocation(centerWidth, centerHeight);676f.show();677numSSs++;678swingSets.add(this);679}680}681682// *******************************************************683// ****************** Utility Methods ********************684// *******************************************************685686/**687* Returns the frame instance688*/689public JFrame getFrame() {690return frame;691}692693/**694* Returns the toolbar695*/696public ToggleButtonToolBar getToolBar() {697return toolbar;698}699700/**701* Returns the toolbar button group702*/703public ButtonGroup getToolBarGroup() {704return toolbarGroup;705}706707/**708* Create a frame for SwingSet2 to reside in if brought up709* as an application.710*/711public static JFrame createFrame(GraphicsConfiguration gc) {712JFrame frame = new JFrame(gc);713if (numSSs == 0) {714frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);715} else {716WindowListener l = new WindowAdapter() {717public void windowClosing(WindowEvent e) {718numSSs--;719swingSets.remove(this);720}721};722frame.addWindowListener(l);723}724return frame;725}726727/**728* Set the status729*/730public void setStatus(String s) {731// do the following on the gui thread732SwingUtilities.invokeLater(new SwingSetRunnable(this, s) {733public void run() {734swingset.statusField.setText((String) obj);735}736});737}738739/**740* This method returns a string from the demo's resource bundle.741*/742public static String getString(String key) {743String value = null;744try {745value = TextAndMnemonicUtils.getTextAndMnemonicString(key);746} catch (MissingResourceException e) {747System.out.println("java.util.MissingResourceException: Couldn't find value for: " + key);748}749if(value == null) {750value = "Could not find resource: " + key + " ";751}752return value;753}754755void setDragEnabled(boolean dragEnabled) {756if (dragEnabled == this.dragEnabled) {757return;758}759760this.dragEnabled = dragEnabled;761762for (DemoModule dm : demosList) {763dm.updateDragEnabled(dragEnabled);764}765766demoSrcPane.setDragEnabled(dragEnabled);767}768769/**770* Returns a mnemonic from the resource bundle. Typically used as771* keyboard shortcuts in menu items.772*/773public char getMnemonic(String key) {774return (getString(key)).charAt(0);775}776777/**778* Creates an icon from an image contained in the "images" directory.779*/780public ImageIcon createImageIcon(String filename, String description) {781String path = "/resources/images/" + filename;782return new ImageIcon(getClass().getResource(path));783}784785/**786* Stores the current L&F, and calls updateLookAndFeel, below787*/788public void setLookAndFeel(LookAndFeelData laf) {789if(!currentLookAndFeel.equals(laf)) {790currentLookAndFeel = laf;791/* The recommended way of synchronizing state between multiple792* controls that represent the same command is to use Actions.793* The code below is a workaround and will be replaced in future794* version of SwingSet2 demo.795*/796String lafName = laf.label;797themesMenu.setEnabled(laf.name.equals("Metal"));798updateLookAndFeel();799for(int i=0;i<lafMenu.getItemCount();i++) {800JMenuItem item = lafMenu.getItem(i);801item.setSelected(item.getText().equals(lafName));802}803}804}805806private void updateThisSwingSet() {807JFrame frame = getFrame();808if (frame == null) {809SwingUtilities.updateComponentTreeUI(this);810} else {811SwingUtilities.updateComponentTreeUI(frame);812}813814SwingUtilities.updateComponentTreeUI(popupMenu);815if (aboutBox != null) {816SwingUtilities.updateComponentTreeUI(aboutBox);817}818}819820/**821* Sets the current L&F on each demo module822*/823public void updateLookAndFeel() {824try {825UIManager.setLookAndFeel(currentLookAndFeel.className);826for (SwingSet2 ss : swingSets) {827ss.updateThisSwingSet();828}829} catch (Exception ex) {830System.out.println("Failed loading L&F: " + currentLookAndFeel);831System.out.println(ex);832}833}834835/**836* Loads and puts the source code text into JEditorPane in the "Source Code" tab837*/838public void setSourceCode(DemoModule demo) {839// do the following on the gui thread840SwingUtilities.invokeLater(new SwingSetRunnable(this, demo) {841public void run() {842swingset.demoSrcPane.setText(((DemoModule)obj).getSourceCode());843swingset.demoSrcPane.setCaretPosition(0);844845}846});847}848849// *******************************************************850// ************** ToggleButtonToolbar *****************851// *******************************************************852static Insets zeroInsets = new Insets(1,1,1,1);853protected class ToggleButtonToolBar extends JToolBar {854public ToggleButtonToolBar() {855super();856}857858JToggleButton addToggleButton(Action a) {859JToggleButton tb = new JToggleButton(860(String)a.getValue(Action.NAME),861(Icon)a.getValue(Action.SMALL_ICON)862);863tb.setName((String)a.getValue(Action.NAME));864tb.setMargin(zeroInsets);865tb.setText(null);866tb.setEnabled(a.isEnabled());867tb.setToolTipText((String)a.getValue(Action.SHORT_DESCRIPTION));868tb.setAction(a);869add(tb);870return tb;871}872}873874// *******************************************************875// ********* ToolBar Panel / Docking Listener ***********876// *******************************************************877class ToolBarPanel extends JPanel implements ContainerListener {878879public boolean contains(int x, int y) {880Component c = getParent();881if (c != null) {882Rectangle r = c.getBounds();883return (x >= 0) && (x < r.width) && (y >= 0) && (y < r.height);884}885else {886return super.contains(x,y);887}888}889890public void componentAdded(ContainerEvent e) {891Container c = e.getContainer().getParent();892if (c != null) {893c.getParent().validate();894c.getParent().repaint();895}896}897898public void componentRemoved(ContainerEvent e) {899Container c = e.getContainer().getParent();900if (c != null) {901c.getParent().validate();902c.getParent().repaint();903}904}905}906907// *******************************************************908// ****************** Runnables ***********************909// *******************************************************910911/**912* Generic SwingSet2 runnable. This is intended to run on the913* AWT gui event thread so as not to muck things up by doing914* gui work off the gui thread. Accepts a SwingSet2 and an Object915* as arguments, which gives subtypes of this class the two916* "must haves" needed in most runnables for this demo.917*/918class SwingSetRunnable implements Runnable {919protected SwingSet2 swingset;920protected Object obj;921922public SwingSetRunnable(SwingSet2 swingset, Object obj) {923this.swingset = swingset;924this.obj = obj;925}926927public void run() {928}929}930931932// *******************************************************933// ******************** Actions ***********************934// *******************************************************935936public class SwitchToDemoAction extends AbstractAction {937SwingSet2 swingset;938DemoModule demo;939940public SwitchToDemoAction(SwingSet2 swingset, DemoModule demo) {941super(demo.getName(), demo.getIcon());942this.swingset = swingset;943this.demo = demo;944}945946public void actionPerformed(ActionEvent e) {947swingset.setDemo(demo);948}949}950951class OkAction extends AbstractAction {952JDialog aboutBox;953954protected OkAction(JDialog aboutBox) {955super("OkAction");956this.aboutBox = aboutBox;957}958959public void actionPerformed(ActionEvent e) {960aboutBox.setVisible(false);961}962}963964class ChangeLookAndFeelAction extends AbstractAction {965SwingSet2 swingset;966LookAndFeelData lafData;967protected ChangeLookAndFeelAction(SwingSet2 swingset, LookAndFeelData lafData) {968super("ChangeTheme");969this.swingset = swingset;970this.lafData = lafData;971}972973public void actionPerformed(ActionEvent e) {974swingset.setLookAndFeel(lafData);975}976}977978class ActivatePopupMenuAction extends AbstractAction {979SwingSet2 swingset;980JPopupMenu popup;981protected ActivatePopupMenuAction(SwingSet2 swingset, JPopupMenu popup) {982super("ActivatePopupMenu");983this.swingset = swingset;984this.popup = popup;985}986987public void actionPerformed(ActionEvent e) {988Dimension invokerSize = getSize();989Dimension popupSize = popup.getPreferredSize();990popup.show(swingset, (invokerSize.width - popupSize.width) / 2,991(invokerSize.height - popupSize.height) / 2);992}993}994995// Turns on all possible auditory feedback996class OnAudioAction extends AbstractAction {997SwingSet2 swingset;998protected OnAudioAction(SwingSet2 swingset) {999super("Audio On");1000this.swingset = swingset;1001}1002public void actionPerformed(ActionEvent e) {1003UIManager.put("AuditoryCues.playList",1004UIManager.get("AuditoryCues.allAuditoryCues"));1005swingset.updateLookAndFeel();1006}1007}10081009// Turns on the default amount of auditory feedback1010class DefaultAudioAction extends AbstractAction {1011SwingSet2 swingset;1012protected DefaultAudioAction(SwingSet2 swingset) {1013super("Audio Default");1014this.swingset = swingset;1015}1016public void actionPerformed(ActionEvent e) {1017UIManager.put("AuditoryCues.playList",1018UIManager.get("AuditoryCues.defaultCueList"));1019swingset.updateLookAndFeel();1020}1021}10221023// Turns off all possible auditory feedback1024class OffAudioAction extends AbstractAction {1025SwingSet2 swingset;1026protected OffAudioAction(SwingSet2 swingset) {1027super("Audio Off");1028this.swingset = swingset;1029}1030public void actionPerformed(ActionEvent e) {1031UIManager.put("AuditoryCues.playList",1032UIManager.get("AuditoryCues.noAuditoryCues"));1033swingset.updateLookAndFeel();1034}1035}10361037// Turns on or off the tool tips for the demo.1038class ToolTipAction extends AbstractAction {1039protected ToolTipAction() {1040super("ToolTip Control");1041}10421043public void actionPerformed(ActionEvent e) {1044boolean status = ((JCheckBoxMenuItem)e.getSource()).isSelected();1045ToolTipManager.sharedInstance().setEnabled(status);1046}1047}10481049class DragSupportAction extends AbstractAction {1050protected DragSupportAction() {1051super("DragSupport Control");1052}10531054public void actionPerformed(ActionEvent e) {1055boolean dragEnabled = ((JCheckBoxMenuItem)e.getSource()).isSelected();1056for (SwingSet2 ss : swingSets) {1057ss.setDragEnabled(dragEnabled);1058}1059}1060}10611062class ChangeThemeAction extends AbstractAction {1063SwingSet2 swingset;1064MetalTheme theme;1065protected ChangeThemeAction(SwingSet2 swingset, MetalTheme theme) {1066super("ChangeTheme");1067this.swingset = swingset;1068this.theme = theme;1069}10701071public void actionPerformed(ActionEvent e) {1072MetalLookAndFeel.setCurrentTheme(theme);1073swingset.updateLookAndFeel();1074}1075}10761077class ExitAction extends AbstractAction {1078SwingSet2 swingset;1079protected ExitAction(SwingSet2 swingset) {1080super("ExitAction");1081this.swingset = swingset;1082}10831084public void actionPerformed(ActionEvent e) {1085System.exit(0);1086}1087}10881089class AboutAction extends AbstractAction {1090SwingSet2 swingset;1091protected AboutAction(SwingSet2 swingset) {1092super("AboutAction");1093this.swingset = swingset;1094}10951096public void actionPerformed(ActionEvent e) {1097if(aboutBox == null) {1098// JPanel panel = new JPanel(new BorderLayout());1099JPanel panel = new AboutPanel(swingset);1100panel.setLayout(new BorderLayout());11011102aboutBox = new JDialog(swingset.getFrame(), getString("AboutBox.title"), false);1103aboutBox.setResizable(false);1104aboutBox.getContentPane().add(panel, BorderLayout.CENTER);11051106// JButton button = new JButton(getString("AboutBox.ok_button_text"));1107JPanel buttonpanel = new JPanel();1108buttonpanel.setBorder(new javax.swing.border.EmptyBorder(0, 0, 3, 0));1109buttonpanel.setOpaque(false);1110JButton button = (JButton) buttonpanel.add(1111new JButton(getString("AboutBox.ok_button_text"))1112);1113panel.add(buttonpanel, BorderLayout.SOUTH);11141115button.addActionListener(new OkAction(aboutBox));1116}1117aboutBox.pack();1118aboutBox.setLocationRelativeTo(getFrame());1119aboutBox.show();1120}1121}11221123class MultiScreenAction extends AbstractAction {1124static final int ALL_SCREENS = -1;1125int screen;1126protected MultiScreenAction(SwingSet2 swingset, int screen) {1127super("MultiScreenAction");1128this.screen = screen;1129}11301131public void actionPerformed(ActionEvent e) {1132GraphicsDevice[] gds = GraphicsEnvironment.1133getLocalGraphicsEnvironment().1134getScreenDevices();1135if (screen == ALL_SCREENS) {1136for (int i = 0; i < gds.length; i++) {1137SwingSet2 swingset = new SwingSet2(1138gds[i].getDefaultConfiguration());1139swingset.setDragEnabled(dragEnabled);1140}1141}1142else {1143SwingSet2 swingset = new SwingSet2(1144gds[screen].getDefaultConfiguration());1145swingset.setDragEnabled(dragEnabled);1146}1147}1148}11491150// *******************************************************1151// ********************** Misc *************************1152// *******************************************************11531154class AboutPanel extends JPanel {1155ImageIcon aboutimage = null;1156SwingSet2 swingset = null;11571158public AboutPanel(SwingSet2 swingset) {1159this.swingset = swingset;1160aboutimage = swingset.createImageIcon("About.jpg", "AboutBox.accessible_description");1161setOpaque(false);1162}11631164public void paint(Graphics g) {1165aboutimage.paintIcon(this, g, 0, 0);1166super.paint(g);1167}11681169public Dimension getPreferredSize() {1170return new Dimension(aboutimage.getIconWidth(),1171aboutimage.getIconHeight());1172}1173}11741175private class ChangeFontAction extends AbstractAction {1176private SwingSet2 swingset;1177private boolean plain;11781179ChangeFontAction(SwingSet2 swingset, boolean plain) {1180super("FontMenu");1181this.swingset = swingset;1182this.plain = plain;1183}11841185public void actionPerformed(ActionEvent e) {1186if (plain) {1187UIManager.put("swing.boldMetal", Boolean.FALSE);1188}1189else {1190UIManager.put("swing.boldMetal", Boolean.TRUE);1191}1192// Change the look and feel to force the settings to take effect.1193updateLookAndFeel();1194}1195}11961197private static LookAndFeelData[] getInstalledLookAndFeelData() {1198return Arrays.stream(UIManager.getInstalledLookAndFeels())1199.map(laf -> getLookAndFeelData(laf))1200.toArray(LookAndFeelData[]::new);1201}12021203private static LookAndFeelData getLookAndFeelData(1204UIManager.LookAndFeelInfo info) {1205switch (info.getName()) {1206case "Metal":1207return new LookAndFeelData(info, "java");1208case "Nimbus":1209return new LookAndFeelData(info, "nimbus");1210case "Windows":1211return new LookAndFeelData(info, "windows");1212case "GTK+":1213return new LookAndFeelData(info, "gtk");1214case "CDE/Motif":1215return new LookAndFeelData(info, "motif");1216case "Mac OS X":1217return new LookAndFeelData(info, "mac");1218default:1219return new LookAndFeelData(info);1220}1221}12221223private static class LookAndFeelData {1224String name;1225String className;1226String label;1227char mnemonic;1228String accDescription;12291230public LookAndFeelData(UIManager.LookAndFeelInfo info) {1231this(info.getName(), info.getClassName(), info.getName(),1232info.getName(), info.getName());1233}12341235public LookAndFeelData(UIManager.LookAndFeelInfo info, String property) {1236this(info.getName(), info.getClassName(),1237getString(String.format("LafMenu.%s_label", property)),1238getString(String.format("LafMenu.%s_mnemonic", property)),1239getString(String.format("LafMenu.%s_accessible_description",1240property)));1241}12421243public LookAndFeelData(String name, String className, String label,1244String mnemonic, String accDescription) {1245this.name = name;1246this.className = className;1247this.label = label;1248this.mnemonic = mnemonic.charAt(0);1249this.accDescription = accDescription;1250}12511252@Override1253public String toString() {1254return className;1255}1256}1257}125812591260