Java tutorial
/* * PS3 Media Server, for streaming any medias to your PS3. * Copyright (C) 2008 A.Brochard * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; version 2 * of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package net.pms.newgui; import com.jgoodies.looks.Options; import com.jgoodies.looks.plastic.PlasticLookAndFeel; import com.sun.jna.Platform; import net.pms.Messages; import net.pms.PMS; import net.pms.configuration.PmsConfiguration; import net.pms.io.WindowsNamedPipe; import net.pms.newgui.update.AutoUpdateDialog; import net.pms.update.AutoUpdater; import net.pms.util.PropertiesUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.metal.DefaultMetalTheme; import javax.swing.plaf.metal.MetalLookAndFeel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.URL; import java.util.Locale; import java.util.Observable; import java.util.Observer; public class LooksFrame extends JFrame implements IFrame, Observer { private static final Logger logger = LoggerFactory.getLogger(LooksFrame.class); private final AutoUpdater autoUpdater; private final PmsConfiguration configuration; public static final String START_SERVICE = "start.service"; private static final long serialVersionUID = 8723727186288427690L; protected static final Dimension preferredSize = new Dimension(1000, 750); // https://code.google.com/p/ps3mediaserver/issues/detail?id=949 protected static final Dimension minimumSize = new Dimension(800, 480); /** * List of context sensitive help pages URLs. These URLs should be relative * to the documentation directory and in the same order as the tabs. The * value <code>null</code> means "don't care", activating the tab will not * change the help page. */ protected static final String[] HELP_PAGES = { "index.html", null, "general_configuration.html", "navigation_share.html", "transcoding.html", null, null }; private NavigationShareTab ft; private StatusTab st; private TracesTab tt; private TranscodingTab tr; private GeneralTab nt; private HelpTab ht; private AbstractButton reload; private JLabel status; private static boolean lookAndFeelInitialized = false; public TracesTab getTt() { return tt; } public NavigationShareTab getFt() { return ft; } public TranscodingTab getTr() { return tr; } public AbstractButton getReload() { return reload; } static void initializeLookAndFeel() { if (lookAndFeelInitialized) { return; } LookAndFeel selectedLaf = null; if (Platform.isWindows()) { try { selectedLaf = (LookAndFeel) Class.forName("com.jgoodies.looks.windows.WindowsLookAndFeel") .newInstance(); } catch (Exception e) { selectedLaf = new PlasticLookAndFeel(); } } else if (System.getProperty("nativelook") == null && !Platform.isMac()) { selectedLaf = new PlasticLookAndFeel(); } else { try { String systemClassName = UIManager.getSystemLookAndFeelClassName(); // workaround for Gnome try { String gtkLAF = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; Class.forName(gtkLAF); if (systemClassName.equals("javax.swing.plaf.metal.MetalLookAndFeel")) { systemClassName = gtkLAF; } } catch (ClassNotFoundException ce) { logger.error("Error loading GTK look and feel: ", ce); } logger.trace("Choosing Java look and feel: " + systemClassName); UIManager.setLookAndFeel(systemClassName); } catch (Exception e1) { selectedLaf = new PlasticLookAndFeel(); logger.error("Error while setting native look and feel: ", e1); } } if (selectedLaf instanceof PlasticLookAndFeel) { PlasticLookAndFeel.setPlasticTheme(PlasticLookAndFeel.createMyDefaultTheme()); PlasticLookAndFeel.setTabStyle(PlasticLookAndFeel.TAB_STYLE_DEFAULT_VALUE); PlasticLookAndFeel.setHighContrastFocusColorsEnabled(false); } else if (selectedLaf != null && selectedLaf.getClass() == MetalLookAndFeel.class) { MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme()); } // Work around caching in MetalRadioButtonUI JRadioButton radio = new JRadioButton(); radio.getUI().uninstallUI(radio); JCheckBox checkBox = new JCheckBox(); checkBox.getUI().uninstallUI(checkBox); if (selectedLaf != null) { try { UIManager.setLookAndFeel(selectedLaf); } catch (UnsupportedLookAndFeelException e) { logger.warn("Can't change look and feel", e); } } lookAndFeelInitialized = true; } /** * Constructs a <code>DemoFrame</code>, configures the UI, * and builds the content. */ public LooksFrame(AutoUpdater autoUpdater, PmsConfiguration configuration) { this.autoUpdater = autoUpdater; this.configuration = configuration; assert this.configuration != null; Options.setDefaultIconSize(new Dimension(18, 18)); Options.setUseNarrowButtons(true); // Global options Options.setTabIconsEnabled(true); UIManager.put(Options.POPUP_DROP_SHADOW_ENABLED_KEY, null); // Swing Settings initializeLookAndFeel(); // wait till the look and feel has been initialized before (possibly) displaying the update notification dialog if (autoUpdater != null) { autoUpdater.addObserver(this); autoUpdater.pollServer(); } // http://propedit.sourceforge.jp/propertieseditor.jnlp Font sf = null; // Set an unicode font for testing exotics languages (japanese) final String language = configuration.getLanguage(); if (language != null && (language.equals("ja") || language.startsWith("zh"))) { sf = new Font("Serif", Font.PLAIN, 12); } if (sf != null) { UIManager.put("Button.font", sf); UIManager.put("ToggleButton.font", sf); UIManager.put("RadioButton.font", sf); UIManager.put("CheckBox.font", sf); UIManager.put("ColorChooser.font", sf); UIManager.put("ToggleButton.font", sf); UIManager.put("ComboBox.font", sf); UIManager.put("ComboBoxItem.font", sf); UIManager.put("InternalFrame.titleFont", sf); UIManager.put("Label.font", sf); UIManager.put("List.font", sf); UIManager.put("MenuBar.font", sf); UIManager.put("Menu.font", sf); UIManager.put("MenuItem.font", sf); UIManager.put("RadioButtonMenuItem.font", sf); UIManager.put("CheckBoxMenuItem.font", sf); UIManager.put("PopupMenu.font", sf); UIManager.put("OptionPane.font", sf); UIManager.put("Panel.font", sf); UIManager.put("ProgressBar.font", sf); UIManager.put("ScrollPane.font", sf); UIManager.put("Viewport", sf); UIManager.put("TabbedPane.font", sf); UIManager.put("TableHeader.font", sf); UIManager.put("TextField.font", sf); UIManager.put("PasswordFiled.font", sf); UIManager.put("TextArea.font", sf); UIManager.put("TextPane.font", sf); UIManager.put("EditorPane.font", sf); UIManager.put("TitledBorder.font", sf); UIManager.put("ToolBar.font", sf); UIManager.put("ToolTip.font", sf); UIManager.put("Tree.font", sf); } setTitle("Test"); setIconImage(readImageIcon("icon-32.png").getImage()); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); JComponent jp = buildContent(); String showScrollbars = System.getProperty("scrollbars", "").toLowerCase(); /* * handle scrollbars: * * 1) forced scrollbars (-Dscrollbars=true): always display them * 2) optional scrollbars (-Dscrollbars=optional): display them as needed * 3) otherwise (default): don't display them */ if (showScrollbars.equals("true")) { setContentPane(new JScrollPane(jp, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS)); } else if (showScrollbars.equals("optional")) { setContentPane(new JScrollPane(jp, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED)); } else { setContentPane(jp); } String projectName = PropertiesUtil.getProjectProperties().get("project.name"); String projectVersion = PropertiesUtil.getProjectProperties().get("project.version"); String title = projectName + " " + projectVersion; // If the version contains a "-" (e.g. "1.50.1-SNAPSHOT" or "1.50.1-beta1"), add a warning message if (projectVersion.indexOf("-") > -1) { title = title + " - " + Messages.getString("LooksFrame.26"); } this.setTitle(title); this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); Dimension screenSize = getToolkit().getScreenSize(); if (screenSize.width < minimumSize.width || screenSize.height < minimumSize.height) { setMinimumSize(screenSize); } else { setMinimumSize(minimumSize); } if (screenSize.width < preferredSize.width || screenSize.height < preferredSize.height) { setSize(screenSize); } else { setSize(preferredSize); } setResizable(true); Dimension paneSize = getSize(); setLocation(((screenSize.width > paneSize.width) ? ((screenSize.width - paneSize.width) / 2) : 0), ((screenSize.height > paneSize.height) ? ((screenSize.height - paneSize.height) / 2) : 0)); if (!configuration.isMinimized() && System.getProperty(START_SERVICE) == null) { setVisible(true); } PMS.get().getRegistry().addSystemTray(this); } protected static ImageIcon readImageIcon(String filename) { URL url = LooksFrame.class.getResource("/resources/images/" + filename); return new ImageIcon(url); } public JComponent buildContent() { JPanel panel = new JPanel(new BorderLayout()); JToolBar toolBar = new JToolBar(); toolBar.setFloatable(false); toolBar.setRollover(true); toolBar.add(new JPanel()); AbstractButton save = createToolBarButton(Messages.getString("LooksFrame.9"), "filesave-48.png", Messages.getString("LooksFrame.9")); save.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PMS.get().save(); } }); toolBar.add(save); toolBar.addSeparator(); reload = createToolBarButton(Messages.getString("LooksFrame.12"), "reload_page-48.png", Messages.getString("LooksFrame.12")); reload.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PMS.get().reset(); } }); toolBar.add(reload); toolBar.addSeparator(); AbstractButton quit = createToolBarButton(Messages.getString("LooksFrame.5"), "exit-48.png", Messages.getString("LooksFrame.5")); quit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { quit(); } }); toolBar.add(quit); if (System.getProperty(START_SERVICE) != null) { quit.setEnabled(false); } toolBar.add(new JPanel()); // Apply the orientation to the toolbar and all components in it Locale locale = new Locale(configuration.getLanguage()); ComponentOrientation orientation = ComponentOrientation.getOrientation(locale); toolBar.applyComponentOrientation(orientation); panel.add(toolBar, BorderLayout.NORTH); panel.add(buildMain(), BorderLayout.CENTER); status = new JLabel(" "); status.setBorder(new CompoundBorder(new EtchedBorder(), new EmptyBorder(0, 5, 0, 5))); status.setComponentOrientation(orientation); // Calling applyComponentOrientation() here would be ideal. // Alas it horribly mutilates the layout of several tabs. // panel.applyComponentOrientation(orientation); panel.add(status, BorderLayout.SOUTH); return panel; } public JComponent buildMain() { final JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP); st = new StatusTab(configuration); tt = new TracesTab(configuration); tr = new TranscodingTab(configuration); nt = new GeneralTab(configuration); ft = new NavigationShareTab(configuration); ht = new HelpTab(); tabbedPane.addTab(Messages.getString("LooksFrame.18"), st.build()); tabbedPane.addTab(Messages.getString("LooksFrame.19"), tt.build()); tabbedPane.addTab(Messages.getString("LooksFrame.20"), nt.build()); tabbedPane.addTab(Messages.getString("LooksFrame.22"), ft.build()); tabbedPane.addTab(Messages.getString("LooksFrame.21"), tr.build()); tabbedPane.addTab(Messages.getString("LooksFrame.24"), ht.build()); tabbedPane.addTab(Messages.getString("LooksFrame.25"), new AboutTab().build()); tabbedPane.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { int selectedIndex = tabbedPane.getSelectedIndex(); if (HELP_PAGES[selectedIndex] != null) { PMS.setHelpPage(HELP_PAGES[selectedIndex]); // Update the contents of the help tab itself ht.updateContents(); } } }); tabbedPane.setBorder(new EmptyBorder(5, 5, 5, 5)); // Set the orientation of the tabbedPane. Note: not using // applyComponentOrientation() here on purpose as it will horribly // mutilate the layout of several tabs. Locale locale = new Locale(configuration.getLanguage()); ComponentOrientation orientation = ComponentOrientation.getOrientation(locale); tabbedPane.setComponentOrientation(orientation); return tabbedPane; } protected AbstractButton createToolBarButton(String text, String iconName, String toolTipText) { JButton button = new JButton(text, readImageIcon(iconName)); button.setToolTipText(toolTipText); button.setFocusable(false); return button; } public void quit() { WindowsNamedPipe.setLoop(false); try { Thread.sleep(100); } catch (InterruptedException e) { logger.error(null, e); } System.exit(0); } @Override public void append(final String msg) { tt.append(msg); } @Override public void setReadValue(long v, String msg) { st.setReadValue(v, msg); } @Override public void setStatusCode(int code, String msg, String icon) { st.getJl().setText(msg); try { st.getImagePanel().set(ImageIO.read(LooksFrame.class.getResourceAsStream("/resources/images/" + icon))); } catch (IOException e) { logger.error(null, e); } } @Override public void setValue(int v, String msg) { st.getJpb().setValue(v); st.getJpb().setString(msg); } /** * This method is being called when a configuration change requiring * a restart of the HTTP server has been done by the user. It should notify the user * to restart the server.<br> * Currently the icon as well as the tool tip text of the restart button is being * changed.<br> * The actions requiring a server restart are defined by {@link PmsConfiguration#NEED_RELOAD_FLAGS} * * @param bool true if the server has to be restarted, false otherwise */ @Override public void setReloadable(boolean bool) { if (bool) { reload.setIcon(readImageIcon("reload_page_required-48.png")); reload.setToolTipText(Messages.getString("LooksFrame.13")); } else { reload.setIcon(readImageIcon("reload_page-48.png")); reload.setToolTipText(Messages.getString("LooksFrame.12")); } } @Override public void addEngines() { tr.addEngines(); } // fired on AutoUpdater state changes public void update(Observable o, Object arg) { if (configuration.isAutoUpdate()) { checkForUpdates(); } } public void checkForUpdates() { if (autoUpdater != null) { try { AutoUpdateDialog.showIfNecessary(this, autoUpdater); } catch (NoClassDefFoundError ncdfe) { logger.error("Error displaying AutoUpdateDialog", ncdfe); } } } public void setStatusLine(String line) { if (line == null) { line = " "; } status.setText(line); } @Override public void addRendererIcon(int code, String msg, String icon) { st.addRendererIcon(code, msg, icon); } @Override public void serverReady() { nt.addRenderers(); nt.addPlugins(); } @Override public void setScanLibraryEnabled(boolean flag) { getFt().setScanLibraryEnabled(flag); } }