From b71f4f4aeb7440b88dd82a252cd296506427c440 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sat, 5 Apr 2008 17:31:05 +0000 Subject: [PATCH] make the GUI update its texts when a new language is chosen git-svn-id: http://trooper/svn/projects/jSite/trunk@611 c3eda9e8-030b-0410-8277-bc7414b0a119 --- .../pterodactylus/jsite/gui/EditNodeDialog.java | 60 ++++++++++--------- src/net/pterodactylus/jsite/gui/I18nAction.java | 22 +++++-- src/net/pterodactylus/jsite/gui/I18nLabel.java | 68 ++++++++++++++++++++++ src/net/pterodactylus/jsite/gui/MainWindow.java | 22 ++++++- .../pterodactylus/jsite/gui/ManageNodesDialog.java | 32 +++++++--- .../pterodactylus/jsite/gui/SwingInterface.java | 14 ++--- src/net/pterodactylus/jsite/i18n/I18n.java | 41 +++++++++++++ src/net/pterodactylus/jsite/i18n/I18nable.java | 35 +++++++++++ 8 files changed, 245 insertions(+), 49 deletions(-) create mode 100644 src/net/pterodactylus/jsite/gui/I18nLabel.java create mode 100644 src/net/pterodactylus/jsite/i18n/I18nable.java diff --git a/src/net/pterodactylus/jsite/gui/EditNodeDialog.java b/src/net/pterodactylus/jsite/gui/EditNodeDialog.java index 2ad2b4b..73602fc 100644 --- a/src/net/pterodactylus/jsite/gui/EditNodeDialog.java +++ b/src/net/pterodactylus/jsite/gui/EditNodeDialog.java @@ -28,19 +28,17 @@ import java.awt.event.ActionEvent; import java.net.InetAddress; import java.net.UnknownHostException; -import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; -import javax.swing.JComponent; import javax.swing.JDialog; -import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.border.EtchedBorder; import net.pterodactylus.jsite.i18n.I18n; +import net.pterodactylus.jsite.i18n.I18nable; import net.pterodactylus.jsite.main.Version; import net.pterodactylus.util.swing.SwingUtils; @@ -50,7 +48,7 @@ import net.pterodactylus.util.swing.SwingUtils; * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ */ -public class EditNodeDialog extends JDialog { +public class EditNodeDialog extends JDialog implements I18nable { /** The user-given name of the node. */ private String name; @@ -65,17 +63,26 @@ public class EditNodeDialog extends JDialog { private boolean sameMachine; /** Action of the okay button. */ - private Action okayAction; + private I18nAction okayAction; /** Action of the cancel button. */ - private Action cancelAction; + private I18nAction cancelAction; + + /** The name label. */ + private I18nLabel nameLabel; /** The name textfield. */ private JTextField nameTextField; + /** The hostname label. */ + private I18nLabel hostnameLabel; + /** The hostname textfield. */ private JTextField hostnameTextField; + /** The port label. */ + private I18nLabel portLabel; + /** The port textfield. */ private JTextField portTextField; @@ -96,6 +103,7 @@ public class EditNodeDialog extends JDialog { initActions(); initComponents(); pack(); + I18n.registerI18nable(this); SwingUtils.center(this); } @@ -246,15 +254,15 @@ public class EditNodeDialog extends JDialog { contentPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(12, 12, 12, 12))); nameTextField = new JTextField(); - contentPanel.add(createLabel(I18n.get("editNodeDialog.label.name"), nameTextField), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); + contentPanel.add(nameLabel = new I18nLabel("editNodeDialog.label.name", nameTextField), new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); contentPanel.add(nameTextField, new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(0, 12, 0, 0), 0, 0)); hostnameTextField = new JTextField(); - contentPanel.add(createLabel(I18n.get("editNodeDialog.label.hostname"), hostnameTextField), new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); + contentPanel.add(hostnameLabel = new I18nLabel("editNodeDialog.label.hostname", hostnameTextField), new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); contentPanel.add(hostnameTextField, new GridBagConstraints(1, 1, 1, 1, 1, 0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(12, 12, 0, 0), 0, 0)); portTextField = new JTextField(); - contentPanel.add(createLabel(I18n.get("editNodeDialog.label.port"), portTextField), new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); + contentPanel.add(portLabel = new I18nLabel("editNodeDialog.label.port", portTextField), new GridBagConstraints(0, 2, 1, 1, 0, 0, GridBagConstraints.LINE_END, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); contentPanel.add(portTextField, new GridBagConstraints(1, 2, 1, 1, 1, 0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(12, 12, 0, 0), 0, 0)); sameMachineCheckBox = new JCheckBox(new I18nAction("editNodeDialog.checkbox.sameMachine") { @@ -266,23 +274,6 @@ public class EditNodeDialog extends JDialog { contentPanel.add(sameMachineCheckBox, new GridBagConstraints(0, 3, 2, 1, 1, 1, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(12, 0, 0, 0), 0, 0)); } - /** - * Creates a label whose name and mnemonic are initialized from the given - * i18n property. - * - * @param i18nBasename - * The i18n property basename of the label - * @param labelFor - * The component this label describes - * @return The created label - */ - private JLabel createLabel(String i18nBasename, JComponent labelFor) { - JLabel label = new JLabel(I18n.get(i18nBasename + ".name")); - label.setDisplayedMnemonic(I18n.getKey(i18nBasename + ".mnemonic")); - label.setLabelFor(labelFor); - return label; - } - // // PRIVATE ACTIONS // @@ -371,4 +362,21 @@ public class EditNodeDialog extends JDialog { setVisible(false); } + // + // INTERFACE I18nable + // + + /** + * {@inheritDoc} + */ + public void updateI18n() { + okayAction.updateI18n(); + cancelAction.updateI18n(); + nameLabel.updateI18n(); + hostnameLabel.updateI18n(); + portLabel.updateI18n(); + setTitle(I18n.get("editNodeDialog.title") + " – jSite " + Version.getVersion()); + SwingUtils.repackCentered(this); + } + } diff --git a/src/net/pterodactylus/jsite/gui/I18nAction.java b/src/net/pterodactylus/jsite/gui/I18nAction.java index 0d36f01..77733ae 100644 --- a/src/net/pterodactylus/jsite/gui/I18nAction.java +++ b/src/net/pterodactylus/jsite/gui/I18nAction.java @@ -5,6 +5,7 @@ import javax.swing.Action; import javax.swing.Icon; import net.pterodactylus.jsite.i18n.I18n; +import net.pterodactylus.jsite.i18n.I18nable; /** * Helper class that initializes actions with values from {@link I18n}. @@ -12,7 +13,10 @@ import net.pterodactylus.jsite.i18n.I18n; * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ */ -public abstract class I18nAction extends AbstractAction { +public abstract class I18nAction extends AbstractAction implements I18nable { + + /** The I18n basename. */ + private final String i18nName; /** * Creates a new action that uses the given name as base name to get values @@ -63,15 +67,23 @@ public abstract class I18nAction extends AbstractAction { * The icon for the action */ public I18nAction(String i18nName, boolean enabled, Icon icon) { + this.i18nName = i18nName; + if (icon != null) { + putValue(Action.SMALL_ICON, icon); + } + setEnabled(enabled); + updateI18n(); + } + + /** + * {@inheritDoc} + */ + public void updateI18n() { putValue(Action.NAME, I18n.get(i18nName + ".name")); putValue(Action.MNEMONIC_KEY, I18n.getKey(i18nName + ".mnemonic")); putValue(Action.ACCELERATOR_KEY, I18n.getKeyStroke(i18nName + ".accelerator")); putValue(Action.SHORT_DESCRIPTION, I18n.get(i18nName + ".shortDescription")); putValue(Action.LONG_DESCRIPTION, I18n.get(i18nName + ".longDescription")); - if (icon != null) { - putValue(Action.SMALL_ICON, icon); - } - setEnabled(enabled); } } \ No newline at end of file diff --git a/src/net/pterodactylus/jsite/gui/I18nLabel.java b/src/net/pterodactylus/jsite/gui/I18nLabel.java new file mode 100644 index 0000000..ffcb549 --- /dev/null +++ b/src/net/pterodactylus/jsite/gui/I18nLabel.java @@ -0,0 +1,68 @@ +/* + * jSite2 - I18nLabel.java - + * Copyright © 2008 David Roden + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.pterodactylus.jsite.gui; + +import java.awt.Component; + +import javax.swing.JLabel; + +import net.pterodactylus.jsite.i18n.I18n; +import net.pterodactylus.jsite.i18n.I18nable; + +/** + * Label that can update itself from {@link I18n}. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + * @version $Id$ + */ +public class I18nLabel extends JLabel implements I18nable { + + /** The I18n basename of the label. */ + private final String i18nBasename; + + /** + * Creates a new label with the given I18n basename that optionally is a + * label for the given component. + * + * @param i18nBasename + * The I18n basename of the label + * @param component + * The component that is activated by the label, or + * null if this label should not activate a + * component + */ + public I18nLabel(String i18nBasename, Component component) { + super(); + this.i18nBasename = i18nBasename; + updateI18n(); + if (component != null) { + setLabelFor(component); + } + } + + /** + * {@inheritDoc} + */ + public void updateI18n() { + setText(I18n.get(i18nBasename + ".name")); + setDisplayedMnemonic(I18n.getKey(i18nBasename + ".mnemonic")); + } + +} diff --git a/src/net/pterodactylus/jsite/gui/MainWindow.java b/src/net/pterodactylus/jsite/gui/MainWindow.java index 681cc32..1142818 100644 --- a/src/net/pterodactylus/jsite/gui/MainWindow.java +++ b/src/net/pterodactylus/jsite/gui/MainWindow.java @@ -30,6 +30,7 @@ import javax.swing.JPanel; import javax.swing.JToolBar; import net.pterodactylus.jsite.i18n.I18n; +import net.pterodactylus.jsite.i18n.I18nable; import net.pterodactylus.jsite.main.Version; import net.pterodactylus.util.swing.StatusBar; import net.pterodactylus.util.swing.SwingUtils; @@ -40,14 +41,14 @@ import net.pterodactylus.util.swing.SwingUtils; * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ */ -public class MainWindow extends JFrame { +public class MainWindow extends JFrame implements I18nable { /** The swing interface that receives all actions. */ private final SwingInterface swingInterface; /** The status bar. */ private StatusBar statusBar = new StatusBar(); - + /** The content pane. */ private JPanel contentPane = new JPanel(); @@ -65,6 +66,7 @@ public class MainWindow extends JFrame { setPreferredSize(new Dimension(480, 280)); pack(); SwingUtils.center(this); + I18n.registerI18nable(this); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } @@ -120,7 +122,7 @@ public class MainWindow extends JFrame { private void initComponents() { super.getContentPane().add(statusBar, BorderLayout.PAGE_END); } - + /** * {@inheritDoc} */ @@ -129,4 +131,18 @@ public class MainWindow extends JFrame { return contentPane; } + // + // INTERFACE I18nable + // + + /** + * {@inheritDoc} + */ + public void updateI18n() { + swingInterface.getManageNodesAction().updateI18n(); + swingInterface.getNodeConnectAction().updateI18n(); + swingInterface.getNodeDisconnectAction().updateI18n(); + SwingUtils.repackCentered(this); + } + } diff --git a/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java b/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java index 9d993a0..447618c 100644 --- a/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java +++ b/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java @@ -28,7 +28,6 @@ import java.util.Iterator; import java.util.List; import javax.swing.AbstractListModel; -import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; @@ -43,6 +42,7 @@ import javax.swing.event.ListSelectionListener; import net.pterodactylus.jsite.core.Core; import net.pterodactylus.jsite.core.Node; import net.pterodactylus.jsite.i18n.I18n; +import net.pterodactylus.jsite.i18n.I18nable; import net.pterodactylus.jsite.main.Version; import net.pterodactylus.util.swing.SwingUtils; @@ -52,7 +52,7 @@ import net.pterodactylus.util.swing.SwingUtils; * @author David ‘Bombe’ Roden <bombe@freenetproject.org> * @version $Id$ */ -public class ManageNodesDialog extends JDialog implements ListSelectionListener { +public class ManageNodesDialog extends JDialog implements ListSelectionListener, I18nable { /** The core. */ private final Core core; @@ -61,19 +61,19 @@ public class ManageNodesDialog extends JDialog implements ListSelectionListener private List originalNodeList; /** The “add node” action. */ - private Action addNodeAction; + private I18nAction addNodeAction; /** The “edit node” action. */ - private Action editNodeAction; + private I18nAction editNodeAction; /** The “delete node” action. */ - private Action deleteNodeAction; + private I18nAction deleteNodeAction; /** The “okay” action. */ - private Action okayAction; + private I18nAction okayAction; /** The “cancel” action. */ - private Action cancelAction; + private I18nAction cancelAction; /** The “edit node” dialog. */ private EditNodeDialog editNodeDialog; @@ -97,6 +97,7 @@ public class ManageNodesDialog extends JDialog implements ListSelectionListener initComponents(); initDialogs(); pack(); + I18n.registerI18nable(this); SwingUtils.center(this); } @@ -338,6 +339,23 @@ public class ManageNodesDialog extends JDialog implements ListSelectionListener deleteNodeAction.setEnabled(selectCount >= 1); } + // + // INTERFACE I18nable + // + + /** + * {@inheritDoc} + */ + public void updateI18n() { + okayAction.updateI18n(); + cancelAction.updateI18n(); + addNodeAction.updateI18n(); + editNodeAction.updateI18n(); + deleteNodeAction.updateI18n(); + setTitle(I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion()); + SwingUtils.repackCentered(this); + } + /** * List model for the {@link ManageNodesDialog#nodeList}. TODO * diff --git a/src/net/pterodactylus/jsite/gui/SwingInterface.java b/src/net/pterodactylus/jsite/gui/SwingInterface.java index edcc0df..4a0c97f 100644 --- a/src/net/pterodactylus/jsite/gui/SwingInterface.java +++ b/src/net/pterodactylus/jsite/gui/SwingInterface.java @@ -22,8 +22,6 @@ package net.pterodactylus.jsite.gui; import java.awt.event.ActionEvent; import java.util.List; -import javax.swing.Action; - import net.pterodactylus.jsite.core.Core; import net.pterodactylus.jsite.core.CoreListener; import net.pterodactylus.jsite.core.Node; @@ -43,13 +41,13 @@ public class SwingInterface implements CoreListener { private MainWindow mainWindow; /** The “manage nodes” action. */ - private Action manageNodesAction; + private I18nAction manageNodesAction; /** The “connect to node” action. */ - private Action nodeConnectAction; + private I18nAction nodeConnectAction; /** The “disconnect from node” action. */ - private Action nodeDisconnectAction; + private I18nAction nodeDisconnectAction; /** The node manager dialog. */ private ManageNodesDialog manageNodesDialog; @@ -96,7 +94,7 @@ public class SwingInterface implements CoreListener { * * @return The “manage nodes” action */ - Action getManageNodesAction() { + I18nAction getManageNodesAction() { return manageNodesAction; } @@ -105,7 +103,7 @@ public class SwingInterface implements CoreListener { * * @return The “connect to node” action */ - Action getNodeConnectAction() { + I18nAction getNodeConnectAction() { return nodeConnectAction; } @@ -114,7 +112,7 @@ public class SwingInterface implements CoreListener { * * @return The “disconnect from node” action */ - Action getNodeDisconnectAction() { + I18nAction getNodeDisconnectAction() { return nodeDisconnectAction; } diff --git a/src/net/pterodactylus/jsite/i18n/I18n.java b/src/net/pterodactylus/jsite/i18n/I18n.java index db97d0b..0acdced 100644 --- a/src/net/pterodactylus/jsite/i18n/I18n.java +++ b/src/net/pterodactylus/jsite/i18n/I18n.java @@ -25,6 +25,8 @@ import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.Properties; @@ -65,6 +67,9 @@ public class I18n { setLocale(Locale.getDefault()); } + /** List of I18nables that are notified when the language changes. */ + private static final List i18nables = new ArrayList(); + /** * Returns the translated value for a key. The translated values may contain * placeholders that are replaced with the given parameters. @@ -176,6 +181,7 @@ public class I18n { inputStream = I18n.class.getResourceAsStream("jSite_" + currentLocale.toString() + ".properties"); if (inputStream != null) { currentLanguage.load(inputStream); + notifyI18nables(); } } catch (MissingResourceException mre1) { currentLocale = Locale.ENGLISH; @@ -185,4 +191,39 @@ public class I18n { Closer.close(inputStream); } } + + /** + * Registers the given I18nable to be updated when the language is changed. + * + * @param i18nable + * The i18nable to register + */ + public static void registerI18nable(I18nable i18nable) { + i18nables.add(i18nable); + } + + /** + * Deregisters the given I18nable to be updated when the language is + * changed. + * + * @param i18nable + * The i18nable to register + */ + public static void deregisterI18nable(I18nable i18nable) { + i18nables.remove(i18nable); + } + + // + // PRIVATE METHODS + // + + /** + * Notifies all registered {@link I18nable}s that the language was changed. + */ + private static void notifyI18nables() { + for (I18nable i18nable: i18nables) { + i18nable.updateI18n(); + } + } + } diff --git a/src/net/pterodactylus/jsite/i18n/I18nable.java b/src/net/pterodactylus/jsite/i18n/I18nable.java new file mode 100644 index 0000000..00e05fe --- /dev/null +++ b/src/net/pterodactylus/jsite/i18n/I18nable.java @@ -0,0 +1,35 @@ +/* + * jSite2 - I18nable.java - + * Copyright © 2008 David Roden + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package net.pterodactylus.jsite.i18n; + +/** + * Interface for objects that want to be notified when the language is changed. + * + * @author David ‘Bombe’ Roden <bombe@freenetproject.org> + * @version $Id$ + */ +public interface I18nable { + + /** + * Notifies the object that the language in {@link I18n} was changed. + */ + public void updateI18n(); + +} -- 2.7.4