001    /* JAPI - (Yet another (hopefully) useful) Java API
002     *
003     * Copyright (C) 2004-2006 Christian Hujer
004     *
005     * This program is free software; you can redistribute it and/or
006     * modify it under the terms of the GNU General Public License as
007     * published by the Free Software Foundation; either version 2 of the
008     * License, or (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful, but
011     * WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013     * General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018     * 02111-1307, USA.
019     */
020    
021    package net.sf.japi.swing.prefs.keys;
022    
023    import java.awt.FlowLayout;
024    import java.awt.Color;
025    import java.awt.Dimension;
026    import java.awt.Component;
027    import java.awt.event.ActionEvent;
028    import java.awt.event.KeyEvent;
029    import javax.swing.JComponent;
030    import javax.swing.BorderFactory;
031    import javax.swing.ButtonGroup;
032    import javax.swing.JRadioButton;
033    import javax.swing.JButton;
034    import javax.swing.AbstractAction;
035    import javax.swing.Action;
036    import javax.swing.KeyStroke;
037    import javax.swing.border.LineBorder;
038    import org.jetbrains.annotations.Nullable;
039    import net.sf.japi.swing.ActionFactory;
040    
041    /** A component for displaying the accellerators of an Action.
042     * @author <a href="mailto:chris@riedquat.de">Christian Hujer</a>
043     */
044    // This class is only public to get the action methods working.
045    public class ActionKeyDisplay extends JComponent {
046    
047        /** Action Factory. */
048        private static final ActionFactory ACTION_FACTORY = ActionFactory.getFactory("net.sf.japi.swing.prefs.keys");
049    
050        /** The action of the button that displays the keystroke and allows changing it. */
051        private final ActionKeyAction actionKeyAction = new ActionKeyAction(this);
052    
053        /** The action that is currently handled. */
054        @Nullable private Action action;
055    
056        /** The radio actions. */
057        private final Action[] radioActions = ACTION_FACTORY.createActions(true, this, "keystrokeNone", "keystrokeStandard", "keystrokeUserdefined");
058    
059        /** Create an ActionKeyDisplay. */
060        public ActionKeyDisplay() {
061            final JButton keyboardButton = new JButton(actionKeyAction);
062            setBorder(BorderFactory.createTitledBorder(ACTION_FACTORY.getString("keystroke.border.title")));
063            setLayout(new FlowLayout(FlowLayout.LEADING));
064            final ButtonGroup bg = new ButtonGroup();
065            for (final Action radioAction : radioActions) {
066                final JRadioButton button = new JRadioButton(radioAction);
067                add(button);
068                bg.add(button);
069            }
070            keyboardButton.setBorder(new LineBorder(Color.BLACK, 4, true));
071            keyboardButton.setPreferredSize(new Dimension(140, 30));
072            keyboardButton.setText("ctrl alt shift pressed N");
073            add(keyboardButton);
074            actionKeyAction.setAction(ACTION_FACTORY.createAction(true, "save"));
075            setEnabled(false);
076        }
077    
078        /** {@inheritDoc} */
079        @Override public void setEnabled(final boolean enabled) {
080            super.setEnabled(enabled);
081            actionKeyAction.setEnabled(enabled);
082            for (final Action radioAction : radioActions) {
083                radioAction.setEnabled(enabled);
084            }
085        }
086    
087        /** Action method for using no keystroke. */
088        public void keystrokeNone() {
089            actionKeyAction.setEnabled(false);
090        }
091    
092        /** Action method for using standard keystroke. */
093        public void keystrokeStandard() {
094            actionKeyAction.setEnabled(false);
095        }
096    
097        /** Action method for using a user defined keystroke. */
098        public void keystrokeUserdefined() {
099            actionKeyAction.setEnabled(true);
100        }
101    
102        /** Returns the action that is currently handled.
103         * @return the action that is currently handled
104         */
105        public Action getAction() {
106            return action;
107        }
108    
109        /** Sets the action that is currently handled.
110         * @param action the action that is currently handled
111         */
112        public void setAction(@Nullable final Action action) {
113            this.action = action;
114            actionKeyAction.setAction(action);
115        }
116    
117    } // class KeyChooser
118    
119    class ActionKeyAction extends AbstractAction {
120    
121        /** The Action to be displayed. */
122        private Action action;
123    
124        private final Component parent;
125    
126        ActionKeyAction(final Component parent) {
127            this.parent = parent;
128        }
129    
130        /** {@inheritDoc} */
131        public void actionPerformed(final ActionEvent e) {
132            //TODO
133        }
134    
135        /** Set the Action to be displayed.
136         * @param action Action to be displayed and changed
137         */
138        public void setAction(@Nullable final Action action) {
139            this.action = action;
140            putValue(Action.NAME, getLocalizedKeyStrokeText(action));
141            setEnabled(action != null);
142        }
143    
144        /** Get the localized text of the keystroke of an Action.
145         * @param action Action to get text for
146         * @return localized text for the accelerator of <var>action</var>
147         * @retval "" if <var>action</var> == null
148         * @retval "" if the accelerator of <var>action</var> == null
149         * @retval String containing localized text for the accelerator of <var>action</var>
150         * @throws ClassCastException in case the bound accelerator property is not a {@link KeyStroke}
151         */
152        public static String getLocalizedKeyStrokeText(final Action action) {
153            if (action == null) {
154                return "";
155            }
156            return getLocalizedKeyStrokeText((KeyStroke) action.getValue(Action.ACCELERATOR_KEY));
157        }
158    
159        /** Get the localized text of a KeyStroke.
160         * @param keyStroke KeyStroke to get text for
161         * @return localized text for the accelerator of <var>action</var>
162         * @retval "" if <var>keyStroke</var> == null
163         * @retval String containing localized text for <var>keyStroke</var>
164         */
165        public static String getLocalizedKeyStrokeText(final KeyStroke keyStroke) {
166            if (keyStroke == null) {
167                return "";
168            }
169            final StringBuilder newName = new StringBuilder();
170            final int modifiers = keyStroke.getModifiers();
171            if (modifiers != 0) {
172                newName.append(KeyEvent.getKeyModifiersText(modifiers));
173                newName.append('+');
174            }
175            final int keyCode = keyStroke.getKeyCode();
176            if (keyCode == 0) {
177                newName.append(keyStroke.getKeyChar());
178            } else {
179                newName.append(KeyEvent.getKeyText(keyCode));
180            }
181            return newName.toString();
182        }
183    
184    } // class ActionKeyAction