/* GanttProject is an opensource project management tool. Copyright (C) 2005-2011 GanttProject Team 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package net.sourceforge.ganttproject.action; import com.google.common.base.Strings; import net.sourceforge.ganttproject.language.GanttLanguage; import net.sourceforge.ganttproject.language.GanttLanguage.Event; import net.sourceforge.ganttproject.util.PropertiesUtil; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.net.URL; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; /** * @author bard */ public abstract class GPAction extends AbstractAction implements GanttLanguage.Listener { private final String myIconSize; private String myFontAwesomeLabel; public enum IconSize { NO_ICON(null), SMALL("8"), MENU("16"), TOOLBAR_SMALL("24"), TOOLBAR_BIG("24"); private final String mySize; IconSize(String size) { mySize = size; } public String asString() { return mySize; } } public static final int MENU_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); /** Location of the icon files */ public static final String ICON_FILE_DIRECTORY = "/icons"; protected boolean iconVisible = true; private final String myName; private KeyStroke myKeyStroke; private static Properties ourKeyboardProperties; private static Properties ourIconProperties; private static GanttLanguage language = GanttLanguage.getInstance(); protected GPAction() { this(null); } public GPAction(String name) { // TODO use icon size given in options as default size this(name, "16"); } protected GPAction(String name, String iconSize) { super(name); myName = name; myIconSize = iconSize; if (iconSize != null) { updateIcon(iconSize); } updateName(); updateTooltip(); language.addListener(this); if (name != null) { myKeyStroke = getKeyStroke(name); putValue(Action.ACCELERATOR_KEY, myKeyStroke); } } protected GPAction(String name, IconSize size) { this(name, size.asString()); } public GPAction withIcon(IconSize size) { final GPAction result = new GPAction(myName, size) { @Override public void actionPerformed(ActionEvent e) { GPAction.this.actionPerformed(e); } @Override public boolean isEnabled() { return GPAction.this.isEnabled(); } }; addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { result.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); } }); return result; } public KeyStroke getKeyStroke() { return myKeyStroke; } private void updateIcon(String iconSize) { Icon icon = createIcon(iconSize); if (icon != null) { putValue(Action.SMALL_ICON, icon); } } protected final Icon createIcon(String iconSize) { if (iconSize == null || false == iconVisible) { return null; } String customIcon = getCustomIconPath(); String resourcePath; if (customIcon == null) { resourcePath = MessageFormat.format("{0}/{1}{2}.gif", ICON_FILE_DIRECTORY, getIconFilePrefix(), iconSize); } else { resourcePath = MessageFormat.format("{0}/{1}x{1}/{2}", ICON_FILE_DIRECTORY, iconSize, customIcon); } URL resource = getClass().getResource(resourcePath); return resource == null ? null : new ImageIcon(resource); } public static final Icon getIcon(String iconSize, String iconFileName) { URL resource = GPAction.class.getResource(MessageFormat.format("{0}/{1}x{1}/{2}", ICON_FILE_DIRECTORY, iconSize, iconFileName)); return resource == null ? null : new ImageIcon(resource); } /** * @return translation of "ID.description" if available, otherwise translation * of "ID" */ protected String getLocalizedDescription() { if (getID() == null) { return null; } String description = getI18n(getID() + ".description"); if (description == null) { description = language.correctLabel(getLocalizedName()); } return description == null ? "" : description; } /** @return translation of ID */ protected String getLocalizedName() { return getID() == null ? null : getI18n(getID()); } public String getID() { return myName; } protected static String getI18n(String key) { return language.getText(key); } protected String getIconFilePrefix() { return null; } protected final void updateName() { if (getFontawesomeLabel() != null) { putValue(Action.NAME, getFontawesomeLabel()); return; } String localizedName = getLocalizedName(); if (localizedName == null) { localizedName = String.valueOf(getValue(Action.NAME)); } if (localizedName != null) { int bucksPos = localizedName.indexOf('$'); if (bucksPos >= 0) { // Get name without the $ in it localizedName = new StringBuffer(localizedName).deleteCharAt(bucksPos).toString(); } putValue(Action.NAME, localizedName); if (bucksPos >= 0) { // Activate mnemonic key putValue(Action.MNEMONIC_KEY, Integer.valueOf(Character.toUpperCase(localizedName.charAt(bucksPos)))); } } } /** * Updates the action. Can be called when external influences resulted in * changed action name and/or description */ public void updateAction() { if (IconSize.TOOLBAR_SMALL.asString().equals(myIconSize) && getFontawesomeLabel() != null) { putValue(Action.SMALL_ICON, null); putValue(Action.NAME, getFontawesomeLabel()); } else { updateName(); } updateTooltip(); } protected void updateTooltip() { String description = getLocalizedDescription(); putValue(Action.SHORT_DESCRIPTION, Strings.isNullOrEmpty(description) ? null : description); } @Override public void languageChanged(Event event) { updateAction(); } private String getCustomIconPath() { if (getID() == null) { return null; } if (ourIconProperties == null) { ourIconProperties = new Properties(); PropertiesUtil.loadProperties(ourIconProperties, "/icons.properties"); } return (String) ourIconProperties.get(getID()); } public String getFontawesomeLabel() { return myFontAwesomeLabel; } protected void setFontAwesomeLabel(String label) { myFontAwesomeLabel = label; updateAction(); } public GPAction asToolbarAction() { return this; } public static List<KeyStroke> getAllKeyStrokes(String keystrokeID) { String text = getKeyStrokeText(keystrokeID); if (text == null) { return Collections.emptyList(); } List<KeyStroke> result = new ArrayList<KeyStroke>(); for (String ksText : text.split(",")) { KeyStroke ks = parseKeyStroke(ksText); if (ks != null) { result.add(ks); } } return result; } public static KeyStroke getKeyStroke(String keystrokeID) { String keystrokeText = getKeyStrokeText(keystrokeID); if (keystrokeText == null) { return null; } return parseKeyStroke(keystrokeText); } private static KeyStroke parseKeyStroke(String keystrokeText) { KeyStroke keyStroke = KeyStroke.getKeyStroke(keystrokeText); if (keyStroke == null) { return null; } if ((keyStroke.getModifiers() & KeyEvent.CTRL_MASK) == KeyEvent.CTRL_MASK || (keyStroke.getModifiers() & KeyEvent.CTRL_DOWN_MASK) == KeyEvent.CTRL_DOWN_MASK) { int modifiers = keyStroke.getModifiers() & (0xffffffff ^ KeyEvent.CTRL_MASK) & (0xffffffff ^ KeyEvent.CTRL_DOWN_MASK) | Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); keyStroke = KeyStroke.getKeyStroke(keyStroke.getKeyCode(), modifiers, keyStroke.isOnKeyRelease()); } return keyStroke; } public static String getKeyStrokeText(String keystrokeID) { if (ourKeyboardProperties == null) { ourKeyboardProperties = new Properties(); PropertiesUtil.loadProperties(ourKeyboardProperties, "/keyboard.properties"); PropertiesUtil.loadProperties(ourKeyboardProperties, "/mouse.properties"); } return (String) ourKeyboardProperties.get(keystrokeID); } public static GPAction createVoidAction(String key) { return new GPAction(key) { @Override public void actionPerformed(ActionEvent e) { // No action } }; } }