/* * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander 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; either version 3 of the License, or * (at your option) any later version. * * muCommander 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, see <http://www.gnu.org/licenses/>. */ package com.mucommander.ui.dialog.pref.theme; import com.mucommander.text.Translator; import com.mucommander.ui.chooser.FontChooser; import com.mucommander.ui.chooser.PreviewLabel; import com.mucommander.ui.dialog.pref.PreferencesDialog; import com.mucommander.ui.dialog.pref.PreferencesPanel; import com.mucommander.ui.layout.ProportionalGridPanel; import com.mucommander.ui.theme.ThemeData; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.util.Vector; /** * Base class for theme editor panels. * <p> * A <code>ThemeEditorPanel</code> is a {@link com.mucommander.ui.dialog.pref.PreferencesPanel} with some * theme specific features: * <ul> * <li>Access to the {@link #themeData ThemeData} being edited.</li> * <li>Helper methods for theme-specific layout creation.</li> * </ul> * </p> * @author Maxence Bernard, Nicolas Rinaudo */ abstract class ThemeEditorPanel extends PreferencesPanel { // - Instance fields ----------------------------------------------------------------- // ----------------------------------------------------------------------------------- /** Edited theme data. */ protected ThemeData themeData; /** Holds references to listeners to prevent them from being garbage collected. */ private java.util.List<ChangeListener> listenerReferences = new Vector<ChangeListener>(); /** Font used to display caption labels. */ private Font captionLabelFont; /** Color used to display caption labels. */ private Color captionTextColor = new Color(48, 48, 48); // - Initialisation ------------------------------------------------------------------ // ----------------------------------------------------------------------------------- /** * Creates a new <code>ThemeEditorPanel</code>. * @param parent dialog in which the panel is stored. * @param title title of the panel. * @param themeData data that is being edited. */ public ThemeEditorPanel(PreferencesDialog parent, String title, ThemeData themeData) { super(parent, title); this.themeData = themeData; // Initialises the caption label font. captionLabelFont = new JLabel().getFont(); captionLabelFont = captionLabelFont.deriveFont(Font.BOLD, captionLabelFont.getSize()-1.5f); } // - Caption label methods ----------------------------------------------------------- // ----------------------------------------------------------------------------------- /** * Creates a caption label containing the specified localised entry. * @param dictionaryKey name of the dictionary entry to use in the label. * @return a caption label containing the specified localised entry. */ protected JLabel createCaptionLabel(String dictionaryKey) { JLabel captionLabel; captionLabel = new JLabel(Translator.get(dictionaryKey)); captionLabel.setFont(captionLabelFont); captionLabel.setForeground(captionTextColor); return captionLabel; } /** * Adds a row with standard color type labels. * <p> * This is a convenience method and is strictly equivalent to calling * <code>{@link #addLabelRow(ProportionalGridPanel,boolean) addLabelRow}(pane, true)</code>. * </p> * @param panel panel in which to add the label row. */ protected void addLabelRow(ProportionalGridPanel panel) {addLabelRow(panel, true);} /** * Adds a row with standard color type labels. * <p> * The labels that will be created are: * <pre> * <EMPTY> | Text | Background | (Preview) * </pre> * </p> * @param panel panel in which to add the label row. * @param includePreview whether or not to add the <code>preview</code> label. */ protected void addLabelRow(ProportionalGridPanel panel, boolean includePreview) { // Skips first column. panel.add(new JLabel()); // Creates the standard labels. panel.add(createCaptionLabel("theme_editor.text")); panel.add(createCaptionLabel("theme_editor.background")); // Adds the preview label if requested. if(includePreview) panel.add(createCaptionLabel("preview")); } // - Font chooser code --------------------------------------------------------------- // ----------------------------------------------------------------------------------- /** * Creates a font chooser that will keep the specified font up-to-date in the current theme data. * @param fontId identifier of the font this chooser will be editing. */ protected FontChooser createFontChooser(int fontId) { FontChooser fontChooser; // Font chooser that will be returned. ChangeListener listener; // Internal listener. // Initialises the font chooser. fontChooser = new FontChooser(themeData.getFont(fontId)); fontChooser.setBorder(BorderFactory.createTitledBorder(Translator.get("theme_editor.font"))); fontChooser.addChangeListener(listener = new ThemeFontChooserListener(themeData, fontId, parent)); // Hold a reference to this listener to prevent garbage collection listenerReferences.add(listener); return fontChooser; } /** * Registers a listener on the specified font chooser. * <p> * The specified listener will receive calls to its <code>setFont</code> method whenever * the font chooser has been updated. * </p> * @param fontChooser chooser to monitor. * @param previewComponent component whose font should be tied to that of the chooser */ protected void addFontChooserListener(FontChooser fontChooser, JComponent previewComponent) { // Update button font when a new font has been chosen in the FontChooser if(fontChooser!=null) { ChangeListener listener; fontChooser.addChangeListener(listener = new PreviewFontChooserListener(previewComponent)); previewComponent.setFont(fontChooser.getCurrentFont()); // Hold a reference to this listener to prevent garbage collection listenerReferences.add(listener); } } // - Scroll pane methods ------------------------------------------------------------- // ----------------------------------------------------------------------------------- /** * Wraps the specified panel within a scroll pane. * <p> * The resulting scroll pane will have a vertical bar as needed, no horizontal scroll bar policy. * </p> * @param panel panel to wrap in a <code>JScrollPane</code>. */ protected JComponent createScrollPane(JPanel panel) { JScrollPane scrollPane; scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setBorder(null); return scrollPane; } // - Color buttons methods ----------------------------------------------------------- // ----------------------------------------------------------------------------------- /** * Adds color buttons to the specified panel. * <p> * This is a convenience method and is strictly equivalent to calling * <code>addColorButtons(gridPanel, fontChooser, label, foregroundId, backgroundId, null)</code>. * </p> * @param gridPanel a 3 columns proportinal grid panel in which to add the buttons. * @param fontChooser used to decide which font to use in each color button's preview. * @param label label for the row. * @param foregroundId identifier of the color to display in the foreground button. * @param backgroundId identifier of the color to display in the background button. */ protected PreviewLabel addColorButtons(ProportionalGridPanel gridPanel, FontChooser fontChooser, String label, int foregroundId, int backgroundId) { return addColorButtons(gridPanel, fontChooser, label, foregroundId, backgroundId, null); } /** * Adds color buttons to the specified panel. * <p> * This method will create a row containing the following items: * <pre> * LABEL | COLOR (foreground) | COLOR (background) * </pre> * </p> * @param gridPanel a 3 columns proportinal grid panel in which to add the buttons. * @param fontChooser used to decide which font to use in each color button's preview. * @param label label for the row. * @param foregroundId identifier of the color to display in the foreground button. * @param backgroundId identifier of the color to display in the background button. * @param comp component to register as a listener on the color buttons. */ protected PreviewLabel addColorButtons(ProportionalGridPanel gridPanel, FontChooser fontChooser, String label, int foregroundId, int backgroundId, JComponent comp) { ColorButton colorButton; PreviewLabel previewLabel; // Adds the row's caption label. gridPanel.add(createCaptionLabel(label)); // Initialises the color buttons' preview label. previewLabel = new PreviewLabel(); previewLabel.setTextPainted(true); addFontChooserListener(fontChooser, previewLabel); // Creates the foreground color button. gridPanel.add(colorButton = new ColorButton(parent, themeData, foregroundId, PreviewLabel.FOREGROUND_COLOR_PROPERTY_NAME, previewLabel)); if(comp != null) colorButton.addUpdatedPreviewComponent(comp); // Creates the background color button. gridPanel.add(colorButton = new ColorButton(parent, themeData, backgroundId, PreviewLabel.BACKGROUND_COLOR_PROPERTY_NAME, previewLabel)); if(comp != null) colorButton.addUpdatedPreviewComponent(comp); return previewLabel; } // - Ad-hoc FontChooser listeners ---------------------------------------------------- // ----------------------------------------------------------------------------------- /** * Used to listen on <code>FontChoosers</code> and update theme data when the font is changed. * @author Nicolas Rinaudo */ private static class ThemeFontChooserListener implements ChangeListener { // - Instance fields ------------------------------------------------------------- // ------------------------------------------------------------------------------- /** Theme data in which to update the font when it changes. */ private ThemeData data; /** Identifier of the font we're listening on. */ private int fontId; /** Parent dialog of this panel **/ private PreferencesDialog dialog; // - Initialisation -------------------------------------------------------------- // ------------------------------------------------------------------------------- /** * Creates a new <code>ThemeFontChooserListener</code>. * @param data theme data to modify when change events are received. * @param fontId identifier of the font that is being listened on. */ public ThemeFontChooserListener(ThemeData data, int fontId, PreferencesDialog dialog) { this.data = data; this.fontId = fontId; this.dialog = dialog; } // - Changes listening ----------------------------------------------------------- // ------------------------------------------------------------------------------- /** * Updates the theme data with the new font value. */ public void stateChanged(ChangeEvent event) { data.setFont(fontId, ((FontChooser)event.getSource()).getCurrentFont()); // Inform the panel's parent dialog that a component in it was changed. dialog.componentChanged(null); } } /** * Used to listen on <code>FontChoosers</code> and update preview components when the font is changed. * @author Nicolas Rinaudo */ private static class PreviewFontChooserListener implements ChangeListener { // - Instance fields ------------------------------------------------------------- // ------------------------------------------------------------------------------- /** Component to update when the font has changed. */ private JComponent preview; // - Initialisation -------------------------------------------------------------- // ------------------------------------------------------------------------------- /** * Creates a new instance of <code>PreviewFontChooserListener</code>. * @param preview component to update when the font has changed. */ public PreviewFontChooserListener(JComponent preview) {this.preview = preview;} // - Changes listening ----------------------------------------------------------- // ------------------------------------------------------------------------------- /** * Updates the preview component. */ public void stateChanged(ChangeEvent event) {preview.setFont(((FontChooser)event.getSource()).getCurrentFont());} } }