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>
44 public class ConfigurationDialog extends JDialog implements I18nable {
46 /** The “okay” action. */
47 private I18nAction okayAction;
49 /** The “cancel” action. */
50 private I18nAction cancelAction;
52 /** The “advanced mode” action. */
53 private I18nAction advancedModeAction;
55 /** The “advanced mode” checkbox. */
56 private JCheckBox advancedModeCheckBox;
58 /** The “beautify GUI” action. */
59 private I18nAction antialiasAction;
61 /** The “use custom control font” action. */
62 private I18nAction useCustomControlFontAction;
64 /** The “use custom user font” action. */
65 private I18nAction useCustomUserFontAction;
67 /** The “use custom L&F” action. */
68 private I18nAction useCustomLAFAction;
70 /** The “restart required” warning label. */
71 private I18nLabel restartRequiredLabel;
73 /** The “beautify” checkbox. */
74 private JCheckBox antialiasCheckBox;
76 /** The “use custom” fonts checkbox. */
77 private JCheckBox useCustomControlFontCheckBox;
79 /** The control font list. */
80 private FontComboBox controlFontList;
82 /** The control font size spinner. */
83 private JSpinner controlFontSizeSpinner;
85 /** The checkbox for “use same as control font”. */
86 private JCheckBox useCustomUserFontCheckBox;
88 /** The user font list. */
89 private FontComboBox userFontList;
91 /** The user font size spinner. */
92 private JSpinner userFontSizeSpinner;
94 /** The checkbox for custom L&F. */
95 private JCheckBox useCustomLAFCheckBox;
97 /** The combo box for the L&Fs. */
98 private JComboBox customLAFComboBox;
100 /** Whether the dialog was cancelled. */
101 private boolean cancelled;
104 * Creates a new configuration dialog.
106 * @param swingInterface
107 * The Swing interface
109 public ConfigurationDialog(SwingInterface swingInterface) {
110 super(swingInterface.getMainWindow(), I18n.get("configurationDialog.title"), true);
114 SwingUtils.center(this);
115 I18n.registerI18nable(this);
123 * Returns whether the dialog was cancelled or confirmed. If the dialog was
124 * cancelled, no further processing should be done.
126 * @return <code>true</code> if the dialog was cancelled,
127 * <code>false</code> otherwise
129 public boolean wasCancelled() {
134 * Returns whether the advanced mode is selected.
136 * @return <code>true</code> if the advanced mode is selected,
137 * <code>false</code> otherwise
139 public boolean isAdvancedMode() {
140 return advancedModeCheckBox.isSelected();
144 * Sets whether the advanced mode is selected.
146 * @param advancedMode
147 * <code>true</code> if the advanced mode is selected,
148 * <code>false</code> otherwise
150 public void setAdvancedMode(boolean advancedMode) {
151 advancedModeCheckBox.setSelected(advancedMode);
155 * Returns whether the “beautify” checkbox has been selected. The result of
156 * this method should not be used if {@link #wasCancelled()} returned
159 * @return <code>true</code> if the checkbox was selected,
160 * <code>false</code> otherwise
162 public boolean isAntialias() {
163 return antialiasCheckBox.isSelected();
167 * Sets the state of the “antialias” checkbox.
170 * The state of the checkbox
172 public void setAntialias(boolean antialias) {
173 antialiasCheckBox.setSelected(antialias);
177 * Returns the font for the controls.
179 * @return The control font, or <code>null</code> if no custom control
182 public String getControlFont() {
183 return useCustomControlFontCheckBox.isSelected() ? controlFontList.getSelectedItem() + "-" + controlFontSizeSpinner.getValue() : null;
187 * Sets the font for the controls.
190 * The control font, or <code>null</code> if no custom control
193 public void setControlFont(String controlFont) {
194 boolean hasControlFont = controlFont != null;
195 useCustomControlFontCheckBox.setSelected(hasControlFont);
196 controlFontList.setEnabled(hasControlFont);
197 controlFontSizeSpinner.setEnabled(hasControlFont);
198 if (hasControlFont) {
199 Font font = Font.decode(controlFont);
200 controlFontSizeSpinner.setValue(font.getSize());
201 controlFontList.setSelectedItem(font.getName());
203 controlFontSizeSpinner.setValue(12);
204 controlFontList.setSelectedItem(null);
209 * Returns the font for user input.
211 * @return The font for user input, or <code>null</code> if no custom user
212 * input font is to be used
214 public String getUserFont() {
215 return useCustomUserFontCheckBox.isSelected() ? userFontList.getSelectedItem() + "-" + userFontSizeSpinner.getValue() : null;
219 * Sets the font for user input.
222 * The font for user input, or <code>null</code> if no custom
223 * user input font is to be used
225 public void setUserFont(String userFont) {
226 boolean hasUserFont = userFont != null;
227 useCustomUserFontCheckBox.setSelected(hasUserFont);
228 userFontList.setEnabled(hasUserFont);
229 userFontSizeSpinner.setEnabled(hasUserFont);
231 Font font = Font.decode(userFont);
232 userFontSizeSpinner.setValue(font.getSize());
233 userFontList.setSelectedItem(font.getName());
235 userFontSizeSpinner.setValue(12);
236 userFontList.setSelectedItem(null);
241 * Returns the class name of the selected look and feel, if a custom look
242 * and feel is selected.
244 * @return The class name of the look and feel to load, or <code>null</code>
245 * if no special look and feel should be used
247 public String getLookAndFeel() {
248 if (!useCustomLAFCheckBox.isSelected()) {
251 return ((LookAndFeelWrapper) customLAFComboBox.getSelectedItem()).getClassName();
255 * Sets the given look and feel.
258 * The class name of the look and feel, or <code>null</code> to
259 * not select a custom look and feel
261 public void setLookAndFeel(String lookAndFeel) {
262 useCustomLAFCheckBox.setSelected(false);
263 customLAFComboBox.setEnabled(false);
264 if (lookAndFeel == null) {
267 for (int lookAndFeelIndex = 0; lookAndFeelIndex < customLAFComboBox.getItemCount(); lookAndFeelIndex++) {
268 LookAndFeelWrapper lookAndFeelWrapper = (LookAndFeelWrapper) customLAFComboBox.getItemAt(lookAndFeelIndex);
269 if (lookAndFeelWrapper.getClassName().equals(lookAndFeel)) {
270 customLAFComboBox.setSelectedIndex(lookAndFeelIndex);
271 customLAFComboBox.setEnabled(true);
272 useCustomLAFCheckBox.setSelected(true);
283 * Creates all actions.
285 private void initActions() {
286 okayAction = new I18nAction("general.button.okay") {
289 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
291 @SuppressWarnings("synthetic-access")
292 public void actionPerformed(ActionEvent actionEvent) {
296 cancelAction = new I18nAction("general.button.cancel") {
299 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
301 @SuppressWarnings("synthetic-access")
302 public void actionPerformed(ActionEvent actionEvent) {
306 advancedModeAction = new I18nAction("configurationDialog.page.interface.item.advancedMode") {
311 public void actionPerformed(ActionEvent e) {
315 antialiasAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.antialias") {
318 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
320 public void actionPerformed(ActionEvent actionEvent) {
324 useCustomControlFontAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.useCustomControlFont") {
329 @SuppressWarnings("synthetic-access")
330 public void actionPerformed(ActionEvent e) {
331 boolean selected = useCustomControlFontCheckBox.isSelected();
332 controlFontList.setEnabled(selected);
333 controlFontSizeSpinner.setEnabled(selected);
336 useCustomUserFontAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.useCustomUserFont") {
341 @SuppressWarnings("synthetic-access")
342 public void actionPerformed(ActionEvent e) {
343 boolean selected = useCustomUserFontCheckBox.isSelected();
344 userFontList.setEnabled(selected);
345 userFontSizeSpinner.setEnabled(selected);
348 useCustomLAFAction = new I18nAction("configurationDialog.page.interfaceTweaks.item.useCustomLAF") {
353 @SuppressWarnings("synthetic-access")
354 public void actionPerformed(ActionEvent e) {
355 customLAFComboBox.setEnabled(useCustomLAFCheckBox.isSelected());
361 * Creates all internal components.
363 private void initComponents() {
364 JPanel contentPane = new JPanel(new BorderLayout(12, 12));
365 contentPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
367 JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
368 contentPane.add(tabbedPane, BorderLayout.CENTER);
370 JComponent interfaceConfig = createInterfaceConfig();
371 tabbedPane.add(I18n.get("configurationDialog.page.interface.name"), interfaceConfig);
373 JComponent interfaceTweaksConfig = createInterfaceTweaksConfig();
374 tabbedPane.add(I18n.get("configurationDialog.page.interfaceTweaks.name"), interfaceTweaksConfig);
376 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
377 contentPane.add(buttonPanel, BorderLayout.PAGE_END);
378 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
379 buttonPanel.add(new JButton(cancelAction));
380 JButton okayButton = new JButton(okayAction);
381 buttonPanel.add(okayButton);
382 getRootPane().setDefaultButton(okayButton);
384 getContentPane().add(contentPane, BorderLayout.CENTER);
388 * Creates the interface configuration panel.
390 * @return The interface configuration panel
392 private JComponent createInterfaceConfig() {
393 JPanel interfaceConfigPanel = new JPanel(new GridBagLayout());
394 interfaceConfigPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
396 advancedModeCheckBox = new JCheckBox(advancedModeAction);
397 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));
399 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));
400 return interfaceConfigPanel;
404 * Creates the panel for the interface tweaks configuration.
406 * @return The interface tweaks configuration panel
408 private JComponent createInterfaceTweaksConfig() {
409 JPanel interfaceTweaksConfigPanel = new JPanel(new GridBagLayout());
410 interfaceTweaksConfigPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
412 restartRequiredLabel = new I18nLabel("configurationDialog.page.interfaceTweaks.item.restartRequired");
413 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));
415 antialiasCheckBox = new JCheckBox(antialiasAction);
416 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));
418 useCustomControlFontCheckBox = new JCheckBox(useCustomControlFontAction);
419 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));
421 controlFontList = new FontComboBox();
422 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));
424 controlFontSizeSpinner = new JSpinner(new SpinnerNumberModel(12, 6, 80, 1));
425 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));
427 useCustomUserFontCheckBox = new JCheckBox(useCustomUserFontAction);
428 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));
430 userFontList = new FontComboBox();
431 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));
433 userFontSizeSpinner = new JSpinner(new SpinnerNumberModel(12, 6, 80, 1));
434 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));
436 useCustomLAFCheckBox = new JCheckBox(useCustomLAFAction);
437 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));
439 LookAndFeelInfo[] lookAndFeelInfos = UIManager.getInstalledLookAndFeels();
440 List<LookAndFeelWrapper> lookAndFeelWrappers = new ArrayList<LookAndFeelWrapper>();
441 for (LookAndFeelInfo lookAndFeelInfo : lookAndFeelInfos) {
442 lookAndFeelWrappers.add(new LookAndFeelWrapper(lookAndFeelInfo.getClassName(), lookAndFeelInfo.getName()));
444 customLAFComboBox = new JComboBox(lookAndFeelWrappers.toArray(new LookAndFeelWrapper[0]));
445 interfaceTweaksConfigPanel.add(customLAFComboBox, new GridBagConstraints(1, 4, 2, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 6, 0, 0), 0, 0));
447 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));
449 return interfaceTweaksConfigPanel;
457 * Called when the “okay” button is clicked.
459 private void actionOkay() {
460 if (useCustomControlFontCheckBox.isSelected()) {
461 if (controlFontList.getSelectedItem() == null) {
462 JOptionPane.showMessageDialog(this, I18n.get("configurationDialog.error.noControlFontSelected.message"), I18n.get("configurationDialog.error.noControlFontSelected.title"), JOptionPane.ERROR_MESSAGE);
466 if (useCustomUserFontCheckBox.isSelected()) {
467 if (userFontList.getSelectedItem() == null) {
468 JOptionPane.showMessageDialog(this, I18n.get("configurationDialog.error.noUserFontSelected.message"), I18n.get("configurationDialog.error.noUserFontSelected.title"), JOptionPane.ERROR_MESSAGE);
477 * Called when the “cancel” button is clicked.
479 private void actionCancel() {
485 // INTERFACE I18nable
489 * @see net.pterodactylus.jsite.i18n.I18nable#updateI18n()
491 public void updateI18n() {
492 okayAction.updateI18n();
493 cancelAction.updateI18n();
494 advancedModeAction.updateI18n();
495 restartRequiredLabel.updateI18n();
496 antialiasAction.updateI18n();
497 useCustomControlFontAction.updateI18n();
498 useCustomUserFontAction.updateI18n();
499 useCustomLAFAction.updateI18n();
500 SwingUtils.repackCentered(this);
504 * Wrapper around class name and name of a {@link LookAndFeel}.
506 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
508 private static class LookAndFeelWrapper {
510 /** The class name of the look and feel. */
511 private final String className;
513 /** The name of a look and feel. */
514 private final String lookAndFeelName;
517 * Creates a new wrapper around the given class name and name of a look
521 * The class name of the look and feel
522 * @param lookAndFeelName
523 * The name of the look and feel
525 public LookAndFeelWrapper(String className, String lookAndFeelName) {
526 this.className = className;
527 this.lookAndFeelName = lookAndFeelName;
531 * Returns the class name of the look and feel.
533 * @return The class name of the look and feel
535 public String getClassName() {
543 public String toString() {
544 return lookAndFeelName;