2 * © 2008 INA Service GmbH
5 package net.pterodactylus.jsite.gui;
7 import java.awt.BorderLayout;
8 import java.awt.FlowLayout;
10 import java.awt.GridBagConstraints;
11 import java.awt.GridBagLayout;
12 import java.awt.Insets;
13 import java.awt.event.ActionEvent;
14 import java.util.ArrayList;
15 import java.util.List;
17 import javax.swing.BorderFactory;
18 import javax.swing.JButton;
19 import javax.swing.JCheckBox;
20 import javax.swing.JComboBox;
21 import javax.swing.JComponent;
22 import javax.swing.JDialog;
23 import javax.swing.JOptionPane;
24 import javax.swing.JPanel;
25 import javax.swing.JSpinner;
26 import javax.swing.JTabbedPane;
27 import javax.swing.LookAndFeel;
28 import javax.swing.SpinnerNumberModel;
29 import javax.swing.SwingConstants;
30 import javax.swing.UIManager;
31 import javax.swing.UIManager.LookAndFeelInfo;
33 import net.pterodactylus.jsite.i18n.I18n;
34 import net.pterodactylus.jsite.i18n.I18nable;
35 import net.pterodactylus.jsite.i18n.gui.I18nAction;
36 import net.pterodactylus.jsite.i18n.gui.I18nLabel;
37 import net.pterodactylus.util.swing.SwingUtils;
40 * The configuration dialog.
42 * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
45 public class ConfigurationDialog extends JDialog implements I18nable {
47 /** The “okay” action. */
48 private I18nAction okayAction;
50 /** The “cancel” action. */
51 private I18nAction cancelAction;
53 /** The “advanced mode” action. */
54 private I18nAction advancedModeAction;
56 /** The “advanced mode” checkbox. */
57 private JCheckBox advancedModeCheckBox;
59 /** The “beautify GUI” action. */
60 private I18nAction antialiasAction;
62 /** The “use custom control font” action. */
63 private I18nAction useCustomControlFontAction;
65 /** The “use custom user font” action. */
66 private I18nAction useCustomUserFontAction;
68 /** The “use custom L&F” action. */
69 private I18nAction useCustomLAFAction;
71 /** The “restart required” warning label. */
72 private I18nLabel restartRequiredLabel;
74 /** The “beautify” checkbox. */
75 private JCheckBox antialiasCheckBox;
77 /** The “use custom” fonts checkbox. */
78 private JCheckBox useCustomControlFontCheckBox;
80 /** The control font list. */
81 private FontComboBox controlFontList;
83 /** The control font size spinner. */
84 private JSpinner controlFontSizeSpinner;
86 /** The checkbox for “use same as control font”. */
87 private JCheckBox useCustomUserFontCheckBox;
89 /** The user font list. */
90 private FontComboBox userFontList;
92 /** The user font size spinner. */
93 private JSpinner userFontSizeSpinner;
95 /** The checkbox for custom L&F. */
96 private JCheckBox useCustomLAFCheckBox;
98 /** The combo box for the L&Fs. */
99 private JComboBox customLAFComboBox;
101 /** Whether the dialog was cancelled. */
102 private boolean cancelled;
105 * Creates a new configuration dialog.
107 * @param swingInterface
108 * The Swing interface
110 public ConfigurationDialog(SwingInterface swingInterface) {
111 super(swingInterface.getMainWindow(), I18n.get("configurationDialog.title"), true);
115 SwingUtils.center(this);
116 I18n.registerI18nable(this);
124 * Returns whether the dialog was cancelled or confirmed. If the dialog was
125 * cancelled, no further processing should be done.
127 * @return <code>true</code> if the dialog was cancelled,
128 * <code>false</code> otherwise
130 public boolean wasCancelled() {
135 * Returns whether the advanced mode is selected.
137 * @return <code>true</code> if the advanced mode is selected,
138 * <code>false</code> otherwise
140 public boolean isAdvancedMode() {
141 return advancedModeCheckBox.isSelected();
145 * Sets whether the advanced mode is selected.
147 * @param advancedMode
148 * <code>true</code> if the advanced mode is selected,
149 * <code>false</code> otherwise
151 public void setAdvancedMode(boolean advancedMode) {
152 advancedModeCheckBox.setSelected(advancedMode);
156 * Returns whether the “beautify” checkbox has been selected. The result of
157 * this method should not be used if {@link #wasCancelled()} returned
160 * @return <code>true</code> if the checkbox was selected,
161 * <code>false</code> otherwise
163 public boolean isAntialias() {
164 return antialiasCheckBox.isSelected();
168 * Sets the state of the “antialias” checkbox.
171 * The state of the checkbox
173 public void setAntialias(boolean antialias) {
174 antialiasCheckBox.setSelected(antialias);
178 * Returns the font for the controls.
180 * @return The control font, or <code>null</code> if no custom control
183 public String getControlFont() {
184 return useCustomControlFontCheckBox.isSelected() ? controlFontList.getSelectedItem() + "-" + controlFontSizeSpinner.getValue() : null;
188 * Sets the font for the controls.
191 * The control font, or <code>null</code> if no custom control
194 public void setControlFont(String controlFont) {
195 boolean hasControlFont = controlFont != null;
196 useCustomControlFontCheckBox.setSelected(hasControlFont);
197 controlFontList.setEnabled(hasControlFont);
198 controlFontSizeSpinner.setEnabled(hasControlFont);
199 if (hasControlFont) {
200 Font font = Font.decode(controlFont);
201 controlFontSizeSpinner.setValue(font.getSize());
202 controlFontList.setSelectedItem(font.getName());
204 controlFontSizeSpinner.setValue(12);
205 controlFontList.setSelectedItem(null);
210 * Returns the font for user input.
212 * @return The font for user input, or <code>null</code> if no custom user
213 * input font is to be used
215 public String getUserFont() {
216 return useCustomUserFontCheckBox.isSelected() ? userFontList.getSelectedItem() + "-" + userFontSizeSpinner.getValue() : null;
220 * Sets the font for user input.
223 * The font for user input, or <code>null</code> if no custom
224 * user input font is to be used
226 public void setUserFont(String userFont) {
227 boolean hasUserFont = userFont != null;
228 useCustomUserFontCheckBox.setSelected(hasUserFont);
229 userFontList.setEnabled(hasUserFont);
230 userFontSizeSpinner.setEnabled(hasUserFont);
232 Font font = Font.decode(userFont);
233 userFontSizeSpinner.setValue(font.getSize());
234 userFontList.setSelectedItem(font.getName());
236 userFontSizeSpinner.setValue(12);
237 userFontList.setSelectedItem(null);
242 * Returns the class name of the selected look and feel, if a custom look
243 * and feel is selected.
245 * @return The class name of the look and feel to load, or <code>null</code>
246 * if no special look and feel should be used
248 public String getLookAndFeel() {
249 if (!useCustomLAFCheckBox.isSelected()) {
252 return ((LookAndFeelWrapper) customLAFComboBox.getSelectedItem()).getClassName();
256 * Sets the given look and feel.
259 * The class name of the look and feel, or <code>null</code> to
260 * not select a custom look and feel
262 public void setLookAndFeel(String lookAndFeel) {
263 useCustomLAFCheckBox.setSelected(false);
264 customLAFComboBox.setEnabled(false);
265 if (lookAndFeel == null) {
268 for (int lookAndFeelIndex = 0; lookAndFeelIndex < customLAFComboBox.getItemCount(); lookAndFeelIndex++) {
269 LookAndFeelWrapper lookAndFeelWrapper = (LookAndFeelWrapper) customLAFComboBox.getItemAt(lookAndFeelIndex);
270 if (lookAndFeelWrapper.getClassName().equals(lookAndFeel)) {
271 customLAFComboBox.setSelectedIndex(lookAndFeelIndex);
272 customLAFComboBox.setEnabled(true);
273 useCustomLAFCheckBox.setSelected(true);
284 * Creates all actions.
286 private void initActions() {
287 okayAction = new I18nAction("general.button.okay") {
290 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
292 @SuppressWarnings("synthetic-access")
293 public void actionPerformed(ActionEvent actionEvent) {
297 cancelAction = new I18nAction("general.button.cancel") {
300 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
302 @SuppressWarnings("synthetic-access")
303 public void actionPerformed(ActionEvent actionEvent) {
307 advancedModeAction = new I18nAction("configurationDialog.page.interface.item.advancedMode") {
312 public void actionPerformed(ActionEvent e) {
316 antialiasAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.antialias") {
319 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
321 public void actionPerformed(ActionEvent actionEvent) {
325 useCustomControlFontAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.useCustomControlFont") {
330 @SuppressWarnings("synthetic-access")
331 public void actionPerformed(ActionEvent e) {
332 boolean selected = useCustomControlFontCheckBox.isSelected();
333 controlFontList.setEnabled(selected);
334 controlFontSizeSpinner.setEnabled(selected);
337 useCustomUserFontAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.useCustomUserFont") {
342 @SuppressWarnings("synthetic-access")
343 public void actionPerformed(ActionEvent e) {
344 boolean selected = useCustomUserFontCheckBox.isSelected();
345 userFontList.setEnabled(selected);
346 userFontSizeSpinner.setEnabled(selected);
349 useCustomLAFAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.useCustomLAF") {
354 @SuppressWarnings("synthetic-access")
355 public void actionPerformed(ActionEvent e) {
356 customLAFComboBox.setEnabled(useCustomLAFCheckBox.isSelected());
362 * Creates all internal components.
364 private void initComponents() {
365 JPanel contentPane = new JPanel(new BorderLayout(12, 12));
366 contentPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
368 JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
369 contentPane.add(tabbedPane, BorderLayout.CENTER);
371 JComponent interfaceConfig = createInterfaceConfig();
372 tabbedPane.add(I18n.get("configurationDialog.page.interface.name"), interfaceConfig);
374 JComponent interfaceTweaksConfig = createInterfaceTweaksConfig();
375 tabbedPane.add(I18n.get("configurationDialog.page.interfaceTweaks.name"), interfaceTweaksConfig);
377 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
378 contentPane.add(buttonPanel, BorderLayout.PAGE_END);
379 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
380 buttonPanel.add(new JButton(cancelAction));
381 JButton okayButton = new JButton(okayAction);
382 buttonPanel.add(okayButton);
383 getRootPane().setDefaultButton(okayButton);
385 getContentPane().add(contentPane, BorderLayout.CENTER);
389 * Creates the interface configuration panel.
391 * @return The interface configuration panel
393 private JComponent createInterfaceConfig() {
394 JPanel interfaceConfigPanel = new JPanel(new GridBagLayout());
395 interfaceConfigPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
397 advancedModeCheckBox = new JCheckBox(advancedModeAction);
398 interfaceConfigPanel.add(advancedModeCheckBox, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
400 interfaceConfigPanel.add(new JPanel(), new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
401 return interfaceConfigPanel;
405 * Creates the panel for the interface tweaks configuration.
407 * @return The interface tweaks configuration panel
409 private JComponent createInterfaceTweaksConfig() {
410 JPanel interfaceTweaksConfigPanel = new JPanel(new GridBagLayout());
411 interfaceTweaksConfigPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
413 restartRequiredLabel = new I18nLabel("configurationDialog.page.interfaceTweaks.item.restartRequired");
414 interfaceTweaksConfigPanel.add(restartRequiredLabel, new GridBagConstraints(0, 0, 3, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
416 antialiasCheckBox = new JCheckBox(antialiasAction);
417 interfaceTweaksConfigPanel.add(antialiasCheckBox, new GridBagConstraints(0, 1, 3, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(18, 0, 0, 0), 0, 0));
419 useCustomControlFontCheckBox = new JCheckBox(useCustomControlFontAction);
420 interfaceTweaksConfigPanel.add(useCustomControlFontCheckBox, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 0, 0, 0), 0, 0));
422 controlFontList = new FontComboBox();
423 interfaceTweaksConfigPanel.add(controlFontList, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 6, 0, 0), 0, 0));
425 controlFontSizeSpinner = new JSpinner(new SpinnerNumberModel(12, 6, 80, 1));
426 interfaceTweaksConfigPanel.add(controlFontSizeSpinner, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 6, 0, 0), 0, 0));
428 useCustomUserFontCheckBox = new JCheckBox(useCustomUserFontAction);
429 interfaceTweaksConfigPanel.add(useCustomUserFontCheckBox, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 0, 0, 0), 0, 0));
431 userFontList = new FontComboBox();
432 interfaceTweaksConfigPanel.add(userFontList, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 6, 0, 0), 0, 0));
434 userFontSizeSpinner = new JSpinner(new SpinnerNumberModel(12, 6, 80, 1));
435 interfaceTweaksConfigPanel.add(userFontSizeSpinner, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 6, 0, 0), 0, 0));
437 useCustomLAFCheckBox = new JCheckBox(useCustomLAFAction);
438 interfaceTweaksConfigPanel.add(useCustomLAFCheckBox, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 0, 0, 0), 0, 0));
440 LookAndFeelInfo[] lookAndFeelInfos = UIManager.getInstalledLookAndFeels();
441 List<LookAndFeelWrapper> lookAndFeelWrappers = new ArrayList<LookAndFeelWrapper>();
442 for (LookAndFeelInfo lookAndFeelInfo: lookAndFeelInfos) {
443 lookAndFeelWrappers.add(new LookAndFeelWrapper(lookAndFeelInfo.getClassName(), lookAndFeelInfo.getName()));
445 customLAFComboBox = new JComboBox(lookAndFeelWrappers.toArray(new LookAndFeelWrapper[0]));
446 interfaceTweaksConfigPanel.add(customLAFComboBox, new GridBagConstraints(1, 4, 2, 1, 1.0, 1.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 6, 0, 0), 0, 0));
448 interfaceTweaksConfigPanel.add(new JPanel(), new GridBagConstraints(0, 5, 3, 1, 1.0, 1.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
450 return interfaceTweaksConfigPanel;
458 * Called when the “okay” button is clicked.
460 private void actionOkay() {
461 if (useCustomControlFontCheckBox.isSelected()) {
462 if (controlFontList.getSelectedItem() == null) {
463 JOptionPane.showMessageDialog(this, I18n.get("configurationDialog.error.noControlFontSelected.message"), I18n.get("configurationDialog.error.noControlFontSelected.title"), JOptionPane.ERROR_MESSAGE);
467 if (useCustomUserFontCheckBox.isSelected()) {
468 if (userFontList.getSelectedItem() == null) {
469 JOptionPane.showMessageDialog(this, I18n.get("configurationDialog.error.noUserFontSelected.message"), I18n.get("configurationDialog.error.noUserFontSelected.title"), JOptionPane.ERROR_MESSAGE);
478 * Called when the “cancel” button is clicked.
480 private void actionCancel() {
486 // INTERFACE I18nable
490 * @see net.pterodactylus.jsite.i18n.I18nable#updateI18n()
492 public void updateI18n() {
493 okayAction.updateI18n();
494 cancelAction.updateI18n();
495 advancedModeAction.updateI18n();
496 restartRequiredLabel.updateI18n();
497 antialiasAction.updateI18n();
498 useCustomControlFontAction.updateI18n();
499 useCustomUserFontAction.updateI18n();
500 useCustomLAFAction.updateI18n();
501 SwingUtils.repackCentered(this);
505 * Wrapper around class name and name of a {@link LookAndFeel}.
507 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
510 private static class LookAndFeelWrapper {
512 /** The class name of the look and feel. */
513 private final String className;
515 /** The name of a look and feel. */
516 private final String lookAndFeelName;
519 * Creates a new wrapper around the given class name and name of a look
523 * The class name of the look and feel
524 * @param lookAndFeelName
525 * The name of the look and feel
527 public LookAndFeelWrapper(String className, String lookAndFeelName) {
528 this.className = className;
529 this.lookAndFeelName = lookAndFeelName;
533 * Returns the class name of the look and feel.
535 * @return The class name of the look and feel
537 public String getClassName() {
545 public String toString() {
546 return lookAndFeelName;