| /* |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| */ |
| package org.apache.batik.util.gui; |
| |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.net.URL; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| import java.util.StringTokenizer; |
| |
| import javax.swing.AbstractAction; |
| import javax.swing.Action; |
| import javax.swing.BorderFactory; |
| import javax.swing.DefaultListModel; |
| import javax.swing.Icon; |
| import javax.swing.ImageIcon; |
| import javax.swing.JButton; |
| import javax.swing.JDialog; |
| import javax.swing.JFrame; |
| import javax.swing.JLabel; |
| import javax.swing.JList; |
| import javax.swing.JPanel; |
| import javax.swing.JScrollPane; |
| import javax.swing.ListCellRenderer; |
| import javax.swing.ListSelectionModel; |
| import javax.swing.event.ListSelectionEvent; |
| import javax.swing.event.ListSelectionListener; |
| |
| import org.apache.batik.util.gui.resource.ActionMap; |
| import org.apache.batik.util.gui.resource.ButtonFactory; |
| import org.apache.batik.util.gui.resource.MissingListenerException; |
| import org.apache.batik.util.resources.ResourceManager; |
| |
| /** |
| * This class represents a language selection dialog. |
| * |
| * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a> |
| * @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a> |
| * @version $Id$ |
| */ |
| public class LanguageDialog extends JDialog implements ActionMap { |
| |
| /** |
| * The return value if 'OK' is chosen. |
| */ |
| public static final int OK_OPTION = 0; |
| |
| /** |
| * The return value if 'Cancel' is chosen. |
| */ |
| public static final int CANCEL_OPTION = 1; |
| |
| /** |
| * The resource file name |
| */ |
| protected static final String RESOURCES = |
| "org.apache.batik.util.gui.resources.LanguageDialogMessages"; |
| |
| /** |
| * The resource bundle |
| */ |
| protected static ResourceBundle bundle; |
| |
| /** |
| * The resource manager |
| */ |
| protected static ResourceManager resources; |
| |
| static { |
| bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); |
| resources = new ResourceManager(bundle); |
| } |
| |
| /** |
| * The map that contains the listeners |
| */ |
| protected Map listeners = new HashMap(); |
| |
| /** |
| * The user languages panel. |
| */ |
| protected Panel panel = new Panel(); |
| |
| /** |
| * The last return code. |
| */ |
| protected int returnCode; |
| |
| /** |
| * Creates a new LanguageDialog object. |
| */ |
| public LanguageDialog(JFrame f) { |
| super(f); |
| setModal(true); |
| setTitle(resources.getString("Dialog.title")); |
| |
| listeners.put("OKButtonAction", new OKButtonAction()); |
| listeners.put("CancelButtonAction", new CancelButtonAction()); |
| |
| getContentPane().add(panel); |
| getContentPane().add( createButtonsPanel(), BorderLayout.SOUTH ); |
| |
| pack(); |
| } |
| |
| /** |
| * Shows the dialog. |
| * @return OK_CANCEL or CANCEL_OPTION. |
| */ |
| public int showDialog() { |
| setVisible(true); |
| return returnCode; |
| } |
| |
| /** |
| * Sets the user languages. |
| */ |
| public void setLanguages(String s) { |
| panel.setLanguages(s); |
| } |
| |
| /** |
| * Returns the user languages. |
| */ |
| public String getLanguages() { |
| return panel.getLanguages(); |
| } |
| |
| // ActionMap implementation /////////////////////////////////////// |
| |
| /** |
| * Returns the action associated with the given string |
| * or null on error |
| * @param key the key mapped with the action to get |
| * @throws MissingListenerException if the action is not found todo does it throw ?? seems to return null |
| */ |
| public Action getAction(String key) throws MissingListenerException { |
| return (Action)listeners.get(key); |
| } |
| |
| /** |
| * Creates the OK/Cancel buttons panel |
| */ |
| protected JPanel createButtonsPanel() { |
| JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT)); |
| ButtonFactory bf = new ButtonFactory(bundle, this); |
| p.add(bf.createJButton("OKButton")); |
| p.add(bf.createJButton("CancelButton")); |
| |
| return p; |
| } |
| |
| /** |
| * The language selection panel. |
| */ |
| public static class Panel extends JPanel implements ActionMap { |
| /** |
| * The user languages list |
| */ |
| protected JList userList; |
| |
| /** |
| * The languages list |
| */ |
| protected JList languageList; |
| |
| /** |
| * The user list model |
| */ |
| protected DefaultListModel userListModel = new DefaultListModel(); |
| |
| /** |
| * The language list model |
| */ |
| protected DefaultListModel languageListModel = new DefaultListModel(); |
| |
| /** |
| * The AddLanguageButton. |
| */ |
| protected JButton addLanguageButton; |
| |
| /** |
| * The RemoveLanguageButton. |
| */ |
| protected JButton removeLanguageButton; |
| |
| /** |
| * The UpLanguageButton. |
| */ |
| protected JButton upLanguageButton; |
| |
| /** |
| * The DownLanguageButton. |
| */ |
| protected JButton downLanguageButton; |
| |
| /** |
| * The ClearLanguageButton. |
| */ |
| protected JButton clearLanguageButton; |
| |
| /** |
| * The map that contains the listeners |
| */ |
| protected Map listeners = new HashMap(); |
| |
| /** |
| * The cached map for country icons (takes more than 2 secs. |
| * to be computed). |
| */ |
| private static Map iconMap = null; |
| |
| /** |
| * Creates a new Panel object. |
| */ |
| public Panel() { |
| super(new GridBagLayout()); |
| |
| initCountryIcons(); |
| |
| setBorder(BorderFactory.createTitledBorder |
| (BorderFactory.createEtchedBorder(), |
| resources.getString("Panel.title"))); |
| |
| listeners.put("AddLanguageButtonAction", |
| new AddLanguageButtonAction()); |
| listeners.put("RemoveLanguageButtonAction", |
| new RemoveLanguageButtonAction()); |
| listeners.put("UpLanguageButtonAction", |
| new UpLanguageButtonAction()); |
| listeners.put("DownLanguageButtonAction", |
| new DownLanguageButtonAction()); |
| listeners.put("ClearLanguageButtonAction", |
| new ClearLanguageButtonAction()); |
| |
| // Initalize the lists |
| userList = new JList(userListModel); |
| userList.setCellRenderer(new IconAndTextCellRenderer()); |
| |
| languageList = new JList(languageListModel); |
| languageList.setCellRenderer(new IconAndTextCellRenderer()); |
| |
| StringTokenizer st; |
| st = new StringTokenizer(resources.getString("Country.list"), " "); |
| while (st.hasMoreTokens()) { |
| languageListModel.addElement(st.nextToken()); |
| } |
| |
| // Layout out the children |
| ExtendedGridBagConstraints constraints = |
| new ExtendedGridBagConstraints(); |
| constraints.insets = new Insets(5, 5, 5, 5); |
| |
| constraints.weightx = 1.0; |
| constraints.weighty = 1.0; |
| constraints.fill = GridBagConstraints.BOTH; |
| |
| // The languages list |
| constraints.setGridBounds(0, 0, 1, 1); |
| JScrollPane sp = new JScrollPane(); |
| sp.setBorder(BorderFactory.createCompoundBorder |
| (BorderFactory.createTitledBorder |
| (BorderFactory.createEmptyBorder(), |
| resources.getString("Languages.title")), |
| BorderFactory.createLoweredBevelBorder())); |
| sp.getViewport().add(languageList); |
| this.add(sp, constraints); |
| |
| languageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
| languageList.addListSelectionListener |
| (new LanguageListSelectionListener()); |
| |
| // The user languages list |
| constraints.setGridBounds(2, 0, 1, 1); |
| |
| JScrollPane sp2 = new JScrollPane(); |
| sp2.setBorder(BorderFactory.createCompoundBorder |
| (BorderFactory.createTitledBorder |
| (BorderFactory.createEmptyBorder(), |
| resources.getString("User.title")), |
| BorderFactory.createLoweredBevelBorder())); |
| sp2.getViewport().add(userList); |
| this.add(sp2, constraints); |
| |
| userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
| userList.addListSelectionListener(new UserListSelectionListener()); |
| |
| // The info label |
| constraints.setGridBounds(0, 1, 3, 1); |
| constraints.weightx = 0; |
| constraints.weighty = 0; |
| this.add(new JLabel(resources.getString("InfoLabel.text")), |
| constraints); |
| |
| // The buttons |
| ButtonFactory bf = new ButtonFactory(bundle, this); |
| JPanel p = new JPanel(new GridLayout(5, 1, 0, 3)); |
| p.add(addLanguageButton = bf.createJButton("AddLanguageButton")); |
| addLanguageButton.setEnabled(false); |
| p.add(removeLanguageButton = |
| bf.createJButton("RemoveLanguageButton")); |
| removeLanguageButton.setEnabled(false); |
| p.add(upLanguageButton = bf.createJButton("UpLanguageButton")); |
| upLanguageButton.setEnabled(false); |
| p.add(downLanguageButton = bf.createJButton("DownLanguageButton")); |
| downLanguageButton.setEnabled(false); |
| p.add(clearLanguageButton = |
| bf.createJButton("ClearLanguageButton")); |
| clearLanguageButton.setEnabled(false); |
| |
| JPanel t = new JPanel(new GridBagLayout()); |
| constraints.setGridBounds(1, 0, 1, 1); |
| this.add(t, constraints); |
| |
| constraints.fill = GridBagConstraints.HORIZONTAL; |
| constraints.setGridBounds(0, 0, 1, 1); |
| constraints.insets = new Insets(0, 0, 0, 0); |
| t.add(p, constraints); |
| |
| sp2.setPreferredSize(sp.getPreferredSize()); |
| } |
| |
| /** |
| * Allows to pre-initialize icons used by the <code>Panel</code> |
| * constructor. It is not neccessary to call it and it should |
| * be called only once. |
| * This method is safe to be called by another thread than the |
| * event thread as it doesn't manipulate Swing <code>JComponent</code> |
| * instances. |
| */ |
| public static synchronized void initCountryIcons() |
| { |
| // don't need to init several times... |
| if (iconMap == null) { |
| iconMap = new HashMap(); |
| StringTokenizer st; |
| st = new StringTokenizer(resources.getString("Country.list"), |
| " "); |
| while (st.hasMoreTokens()) { |
| computeCountryIcon(LanguageDialog.Panel.class, |
| st.nextToken()); |
| } |
| } |
| } |
| |
| /** |
| * Returns the selected user languages. |
| */ |
| public String getLanguages() { |
| StringBuffer result = new StringBuffer(); |
| if (userListModel.getSize() > 0) { |
| result.append(userListModel.getElementAt(0)); |
| |
| for (int i = 1; i < userListModel.getSize(); i++) { |
| result.append( ',' ); |
| result.append( userListModel.getElementAt(i) ); |
| } |
| } |
| return result.toString(); |
| } |
| |
| /** |
| * Sets the user languages. |
| */ |
| public void setLanguages(String str) { |
| int len = userListModel.getSize(); |
| for (int i = 0; i < len; i++) { |
| Object o = userListModel.getElementAt(0); |
| userListModel.removeElementAt(0); |
| String userListModelStr = (String)o; |
| |
| int size = languageListModel.getSize(); |
| int n = 0; |
| while (n < size) { |
| String s = (String)languageListModel.getElementAt(n); |
| if (userListModelStr.compareTo(s) > 0) { |
| break; |
| } |
| n++; |
| } |
| languageListModel.insertElementAt(o, n); |
| } |
| |
| StringTokenizer st; |
| st = new StringTokenizer(str, ","); |
| while (st.hasMoreTokens()) { |
| String s = st.nextToken(); |
| userListModel.addElement(s); |
| languageListModel.removeElement(s); |
| } |
| |
| updateButtons(); |
| } |
| |
| /** |
| * Updates the state of the buttons |
| */ |
| protected void updateButtons() { |
| int size = userListModel.size(); |
| int i = userList.getSelectedIndex(); |
| |
| boolean empty = size == 0; |
| boolean selected = i != -1; |
| boolean zeroSelected = i == 0; |
| boolean lastSelected = i == size - 1; |
| |
| removeLanguageButton.setEnabled(!empty && selected); |
| upLanguageButton.setEnabled(!empty && selected && !zeroSelected); |
| downLanguageButton.setEnabled(!empty && selected && !lastSelected); |
| clearLanguageButton.setEnabled(!empty); |
| |
| size = languageListModel.size(); |
| i = languageList.getSelectedIndex(); |
| |
| empty = size == 0; |
| selected = i != -1; |
| |
| addLanguageButton.setEnabled(!empty && selected); |
| } |
| |
| /** |
| * returns the full string associated with a country code. |
| */ |
| protected String getCountryText(String code) { |
| return resources.getString(code + ".text"); |
| } |
| |
| /** |
| * returns the icon associated with a country code. |
| */ |
| protected Icon getCountryIcon(String code) { |
| return computeCountryIcon(getClass(), code); |
| } |
| |
| private static Icon computeCountryIcon(Class ref, |
| String code) { |
| ImageIcon icon = null; |
| try { |
| if ((icon = (ImageIcon)iconMap.get(code)) != null) |
| return icon; |
| String s = resources.getString(code + ".icon"); |
| URL url = ref.getResource(s); |
| if (url != null) { |
| iconMap.put(code, icon = new ImageIcon(url)); |
| return icon; |
| } |
| } catch (MissingResourceException e) { |
| } |
| return new ImageIcon(ref.getResource("resources/blank.gif")); |
| } |
| |
| // ActionMap implementation /////////////////////////////////////// |
| |
| /** |
| * Returns the action associated with the given string |
| * or null on error |
| * @param key the key mapped with the action to get |
| * @throws MissingListenerException if the action is not found |
| */ |
| public Action getAction(String key) throws MissingListenerException { |
| return (Action)listeners.get(key); |
| } |
| |
| /** |
| * The action associated with the 'add' button |
| */ |
| protected class AddLanguageButtonAction extends AbstractAction { |
| public void actionPerformed(ActionEvent e) { |
| int i = languageList.getSelectedIndex(); |
| Object o = languageListModel.getElementAt(i); |
| languageListModel.removeElementAt(i); |
| userListModel.addElement(o); |
| userList.setSelectedValue(o, true); |
| } |
| } |
| |
| /** |
| * The action associated with the 'remove' button |
| */ |
| protected class RemoveLanguageButtonAction extends AbstractAction { |
| public void actionPerformed(ActionEvent e) { |
| int i = userList.getSelectedIndex(); |
| Object o = userListModel.getElementAt(i); |
| userListModel.removeElementAt(i); |
| String userListModelStr = (String)o; |
| int size = languageListModel.getSize(); |
| int n = 0; |
| while (n < size) { |
| String s = (String)languageListModel.getElementAt(n); |
| if (userListModelStr.compareTo(s) > 0) { |
| break; |
| } |
| n++; |
| } |
| languageListModel.insertElementAt(o, n); |
| languageList.setSelectedValue(o, true); |
| updateButtons(); |
| } |
| } |
| |
| /** |
| * The action associated with the 'up' button |
| */ |
| protected class UpLanguageButtonAction extends AbstractAction { |
| public void actionPerformed(ActionEvent e) { |
| int i = userList.getSelectedIndex(); |
| Object o = userListModel.getElementAt(i); |
| userListModel.removeElementAt(i); |
| userListModel.insertElementAt(o, i - 1); |
| userList.setSelectedIndex(i - 1); |
| } |
| } |
| |
| /** |
| * The action associated with the 'down' button |
| */ |
| protected class DownLanguageButtonAction extends AbstractAction { |
| public void actionPerformed(ActionEvent e) { |
| int i = userList.getSelectedIndex(); |
| Object o = userListModel.getElementAt(i); |
| userListModel.removeElementAt(i); |
| userListModel.insertElementAt(o, i + 1); |
| userList.setSelectedIndex(i + 1); |
| } |
| } |
| |
| /** |
| * The action associated with the 'clear' button |
| */ |
| protected class ClearLanguageButtonAction extends AbstractAction { |
| public void actionPerformed(ActionEvent e) { |
| int len = userListModel.getSize(); |
| for (int i = 0; i < len; i++) { |
| Object o = userListModel.getElementAt(0); |
| userListModel.removeElementAt(0); |
| String userListModelStr = (String)o; |
| |
| int size = languageListModel.getSize(); |
| int n = 0; |
| while (n < size) { |
| String s = (String)languageListModel.getElementAt(n); |
| if (userListModelStr.compareTo(s) > 0) { |
| break; |
| } |
| n++; |
| } |
| languageListModel.insertElementAt(o, n); |
| } |
| updateButtons(); |
| } |
| } |
| |
| /** |
| * To manage selection modifications |
| */ |
| protected class LanguageListSelectionListener |
| implements ListSelectionListener { |
| public void valueChanged(ListSelectionEvent e) { |
| int i = languageList.getSelectedIndex(); |
| userList.getSelectionModel().clearSelection(); |
| languageList.setSelectedIndex(i); |
| updateButtons(); |
| } |
| } |
| |
| /** |
| * To manage selection modifications |
| */ |
| protected class UserListSelectionListener |
| implements ListSelectionListener { |
| public void valueChanged(ListSelectionEvent e) { |
| int i = userList.getSelectedIndex(); |
| languageList.getSelectionModel().clearSelection(); |
| userList.setSelectedIndex(i); |
| updateButtons(); |
| } |
| } |
| |
| /** |
| * To display icons and text in the lists. |
| */ |
| protected class IconAndTextCellRenderer |
| extends JLabel |
| implements ListCellRenderer { |
| public IconAndTextCellRenderer() { |
| this.setOpaque(true); |
| this.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); |
| } |
| public Component getListCellRendererComponent(JList list, |
| Object value, |
| int index, |
| boolean isSelected, |
| boolean cellHasFocus){ |
| String s = (String)value; |
| this.setText(getCountryText(s)); |
| this.setIcon(getCountryIcon(s)); |
| this.setEnabled(list.isEnabled()); |
| this.setFont(list.getFont()); |
| if (isSelected) { |
| this.setBackground(list.getSelectionBackground()); |
| this.setForeground(list.getSelectionForeground()); |
| } else { |
| this.setBackground(list.getBackground()); |
| this.setForeground(list.getForeground()); |
| } |
| return this; |
| } |
| } |
| } |
| |
| /** |
| * The action associated with the 'OK' button |
| */ |
| protected class OKButtonAction extends AbstractAction { |
| public void actionPerformed(ActionEvent e) { |
| returnCode = OK_OPTION; |
| dispose(); |
| } |
| } |
| |
| /** |
| * The action associated with the 'Cancel' button |
| */ |
| protected class CancelButtonAction extends AbstractAction { |
| public void actionPerformed(ActionEvent e) { |
| returnCode = CANCEL_OPTION; |
| dispose(); |
| } |
| } |
| } |