PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/com/mucommander/ui/dialog/pref/theme/ThemeEditorPanel.java

https://bitbucket.org/userdima/mucommander
Java | 331 lines | 100 code | 55 blank | 176 comment | 6 complexity | e335c20fa7626356e1e453c7b5a260b8 MD5 | raw file
  1. /*
  2. * This file is part of muCommander, http://www.mucommander.com
  3. * Copyright (C) 2002-2012 Maxence Bernard
  4. *
  5. * muCommander is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * muCommander is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. package com.mucommander.ui.dialog.pref.theme;
  19. import com.mucommander.text.Translator;
  20. import com.mucommander.ui.chooser.FontChooser;
  21. import com.mucommander.ui.chooser.PreviewLabel;
  22. import com.mucommander.ui.dialog.pref.PreferencesDialog;
  23. import com.mucommander.ui.dialog.pref.PreferencesPanel;
  24. import com.mucommander.ui.layout.ProportionalGridPanel;
  25. import com.mucommander.ui.theme.ThemeData;
  26. import javax.swing.*;
  27. import javax.swing.event.ChangeEvent;
  28. import javax.swing.event.ChangeListener;
  29. import java.awt.*;
  30. import java.util.Vector;
  31. /**
  32. * Base class for theme editor panels.
  33. * <p>
  34. * A <code>ThemeEditorPanel</code> is a {@link com.mucommander.ui.dialog.pref.PreferencesPanel} with some
  35. * theme specific features:
  36. * <ul>
  37. * <li>Access to the {@link #themeData ThemeData} being edited.</li>
  38. * <li>Helper methods for theme-specific layout creation.</li>
  39. * </ul>
  40. * </p>
  41. * @author Maxence Bernard, Nicolas Rinaudo
  42. */
  43. abstract class ThemeEditorPanel extends PreferencesPanel {
  44. // - Instance fields -----------------------------------------------------------------
  45. // -----------------------------------------------------------------------------------
  46. /** Edited theme data. */
  47. protected ThemeData themeData;
  48. /** Holds references to listeners to prevent them from being garbage collected. */
  49. private java.util.List<ChangeListener> listenerReferences = new Vector<ChangeListener>();
  50. /** Font used to display caption labels. */
  51. private Font captionLabelFont;
  52. /** Color used to display caption labels. */
  53. private Color captionTextColor = new Color(48, 48, 48);
  54. // - Initialisation ------------------------------------------------------------------
  55. // -----------------------------------------------------------------------------------
  56. /**
  57. * Creates a new <code>ThemeEditorPanel</code>.
  58. * @param parent dialog in which the panel is stored.
  59. * @param title title of the panel.
  60. * @param themeData data that is being edited.
  61. */
  62. public ThemeEditorPanel(PreferencesDialog parent, String title, ThemeData themeData) {
  63. super(parent, title);
  64. this.themeData = themeData;
  65. // Initialises the caption label font.
  66. captionLabelFont = new JLabel().getFont();
  67. captionLabelFont = captionLabelFont.deriveFont(Font.BOLD, captionLabelFont.getSize()-1.5f);
  68. }
  69. // - Caption label methods -----------------------------------------------------------
  70. // -----------------------------------------------------------------------------------
  71. /**
  72. * Creates a caption label containing the specified localised entry.
  73. * @param dictionaryKey name of the dictionary entry to use in the label.
  74. * @return a caption label containing the specified localised entry.
  75. */
  76. protected JLabel createCaptionLabel(String dictionaryKey) {
  77. JLabel captionLabel;
  78. captionLabel = new JLabel(Translator.get(dictionaryKey));
  79. captionLabel.setFont(captionLabelFont);
  80. captionLabel.setForeground(captionTextColor);
  81. return captionLabel;
  82. }
  83. /**
  84. * Adds a row with standard color type labels.
  85. * <p>
  86. * This is a convenience method and is strictly equivalent to calling
  87. * <code>{@link #addLabelRow(ProportionalGridPanel,boolean) addLabelRow}(pane, true)</code>.
  88. * </p>
  89. * @param panel panel in which to add the label row.
  90. */
  91. protected void addLabelRow(ProportionalGridPanel panel) {addLabelRow(panel, true);}
  92. /**
  93. * Adds a row with standard color type labels.
  94. * <p>
  95. * The labels that will be created are:
  96. * <pre>
  97. * &lt;EMPTY&gt; | Text | Background | (Preview)
  98. * </pre>
  99. * </p>
  100. * @param panel panel in which to add the label row.
  101. * @param includePreview whether or not to add the <code>preview</code> label.
  102. */
  103. protected void addLabelRow(ProportionalGridPanel panel, boolean includePreview) {
  104. // Skips first column.
  105. panel.add(new JLabel());
  106. // Creates the standard labels.
  107. panel.add(createCaptionLabel("theme_editor.text"));
  108. panel.add(createCaptionLabel("theme_editor.background"));
  109. // Adds the preview label if requested.
  110. if(includePreview)
  111. panel.add(createCaptionLabel("preview"));
  112. }
  113. // - Font chooser code ---------------------------------------------------------------
  114. // -----------------------------------------------------------------------------------
  115. /**
  116. * Creates a font chooser that will keep the specified font up-to-date in the current theme data.
  117. * @param fontId identifier of the font this chooser will be editing.
  118. */
  119. protected FontChooser createFontChooser(int fontId) {
  120. FontChooser fontChooser; // Font chooser that will be returned.
  121. ChangeListener listener; // Internal listener.
  122. // Initialises the font chooser.
  123. fontChooser = new FontChooser(themeData.getFont(fontId));
  124. fontChooser.setBorder(BorderFactory.createTitledBorder(Translator.get("theme_editor.font")));
  125. fontChooser.addChangeListener(listener = new ThemeFontChooserListener(themeData, fontId, parent));
  126. // Hold a reference to this listener to prevent garbage collection
  127. listenerReferences.add(listener);
  128. return fontChooser;
  129. }
  130. /**
  131. * Registers a listener on the specified font chooser.
  132. * <p>
  133. * The specified listener will receive calls to its <code>setFont</code> method whenever
  134. * the font chooser has been updated.
  135. * </p>
  136. * @param fontChooser chooser to monitor.
  137. * @param previewComponent component whose font should be tied to that of the chooser
  138. */
  139. protected void addFontChooserListener(FontChooser fontChooser, JComponent previewComponent) {
  140. // Update button font when a new font has been chosen in the FontChooser
  141. if(fontChooser!=null) {
  142. ChangeListener listener;
  143. fontChooser.addChangeListener(listener = new PreviewFontChooserListener(previewComponent));
  144. previewComponent.setFont(fontChooser.getCurrentFont());
  145. // Hold a reference to this listener to prevent garbage collection
  146. listenerReferences.add(listener);
  147. }
  148. }
  149. // - Scroll pane methods -------------------------------------------------------------
  150. // -----------------------------------------------------------------------------------
  151. /**
  152. * Wraps the specified panel within a scroll pane.
  153. * <p>
  154. * The resulting scroll pane will have a vertical bar as needed, no horizontal scroll bar policy.
  155. * </p>
  156. * @param panel panel to wrap in a <code>JScrollPane</code>.
  157. */
  158. protected JComponent createScrollPane(JPanel panel) {
  159. JScrollPane scrollPane;
  160. scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  161. scrollPane.setBorder(null);
  162. return scrollPane;
  163. }
  164. // - Color buttons methods -----------------------------------------------------------
  165. // -----------------------------------------------------------------------------------
  166. /**
  167. * Adds color buttons to the specified panel.
  168. * <p>
  169. * This is a convenience method and is strictly equivalent to calling
  170. * <code>addColorButtons(gridPanel, fontChooser, label, foregroundId, backgroundId, null)</code>.
  171. * </p>
  172. * @param gridPanel a 3 columns proportinal grid panel in which to add the buttons.
  173. * @param fontChooser used to decide which font to use in each color button's preview.
  174. * @param label label for the row.
  175. * @param foregroundId identifier of the color to display in the foreground button.
  176. * @param backgroundId identifier of the color to display in the background button.
  177. */
  178. protected PreviewLabel addColorButtons(ProportionalGridPanel gridPanel, FontChooser fontChooser, String label, int foregroundId, int backgroundId) {
  179. return addColorButtons(gridPanel, fontChooser, label, foregroundId, backgroundId, null);
  180. }
  181. /**
  182. * Adds color buttons to the specified panel.
  183. * <p>
  184. * This method will create a row containing the following items:
  185. * <pre>
  186. * LABEL | COLOR (foreground) | COLOR (background)
  187. * </pre>
  188. * </p>
  189. * @param gridPanel a 3 columns proportinal grid panel in which to add the buttons.
  190. * @param fontChooser used to decide which font to use in each color button's preview.
  191. * @param label label for the row.
  192. * @param foregroundId identifier of the color to display in the foreground button.
  193. * @param backgroundId identifier of the color to display in the background button.
  194. * @param comp component to register as a listener on the color buttons.
  195. */
  196. protected PreviewLabel addColorButtons(ProportionalGridPanel gridPanel, FontChooser fontChooser, String label, int foregroundId, int backgroundId, JComponent comp) {
  197. ColorButton colorButton;
  198. PreviewLabel previewLabel;
  199. // Adds the row's caption label.
  200. gridPanel.add(createCaptionLabel(label));
  201. // Initialises the color buttons' preview label.
  202. previewLabel = new PreviewLabel();
  203. previewLabel.setTextPainted(true);
  204. addFontChooserListener(fontChooser, previewLabel);
  205. // Creates the foreground color button.
  206. gridPanel.add(colorButton = new ColorButton(parent, themeData, foregroundId, PreviewLabel.FOREGROUND_COLOR_PROPERTY_NAME, previewLabel));
  207. if(comp != null)
  208. colorButton.addUpdatedPreviewComponent(comp);
  209. // Creates the background color button.
  210. gridPanel.add(colorButton = new ColorButton(parent, themeData, backgroundId, PreviewLabel.BACKGROUND_COLOR_PROPERTY_NAME, previewLabel));
  211. if(comp != null)
  212. colorButton.addUpdatedPreviewComponent(comp);
  213. return previewLabel;
  214. }
  215. // - Ad-hoc FontChooser listeners ----------------------------------------------------
  216. // -----------------------------------------------------------------------------------
  217. /**
  218. * Used to listen on <code>FontChoosers</code> and update theme data when the font is changed.
  219. * @author Nicolas Rinaudo
  220. */
  221. private static class ThemeFontChooserListener implements ChangeListener {
  222. // - Instance fields -------------------------------------------------------------
  223. // -------------------------------------------------------------------------------
  224. /** Theme data in which to update the font when it changes. */
  225. private ThemeData data;
  226. /** Identifier of the font we're listening on. */
  227. private int fontId;
  228. /** Parent dialog of this panel **/
  229. private PreferencesDialog dialog;
  230. // - Initialisation --------------------------------------------------------------
  231. // -------------------------------------------------------------------------------
  232. /**
  233. * Creates a new <code>ThemeFontChooserListener</code>.
  234. * @param data theme data to modify when change events are received.
  235. * @param fontId identifier of the font that is being listened on.
  236. */
  237. public ThemeFontChooserListener(ThemeData data, int fontId, PreferencesDialog dialog) {
  238. this.data = data;
  239. this.fontId = fontId;
  240. this.dialog = dialog;
  241. }
  242. // - Changes listening -----------------------------------------------------------
  243. // -------------------------------------------------------------------------------
  244. /**
  245. * Updates the theme data with the new font value.
  246. */
  247. public void stateChanged(ChangeEvent event) {
  248. data.setFont(fontId, ((FontChooser)event.getSource()).getCurrentFont());
  249. // Inform the panel's parent dialog that a component in it was changed.
  250. dialog.componentChanged(null);
  251. }
  252. }
  253. /**
  254. * Used to listen on <code>FontChoosers</code> and update preview components when the font is changed.
  255. * @author Nicolas Rinaudo
  256. */
  257. private static class PreviewFontChooserListener implements ChangeListener {
  258. // - Instance fields -------------------------------------------------------------
  259. // -------------------------------------------------------------------------------
  260. /** Component to update when the font has changed. */
  261. private JComponent preview;
  262. // - Initialisation --------------------------------------------------------------
  263. // -------------------------------------------------------------------------------
  264. /**
  265. * Creates a new instance of <code>PreviewFontChooserListener</code>.
  266. * @param preview component to update when the font has changed.
  267. */
  268. public PreviewFontChooserListener(JComponent preview) {this.preview = preview;}
  269. // - Changes listening -----------------------------------------------------------
  270. // -------------------------------------------------------------------------------
  271. /**
  272. * Updates the preview component.
  273. */
  274. public void stateChanged(ChangeEvent event) {preview.setFont(((FontChooser)event.getSource()).getCurrentFont());}
  275. }
  276. }