All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openbp.jaspira.action.JaspiraAction Maven / Gradle / Ivy

The newest version!
/*
 *   Licensed 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.openbp.jaspira.action;

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeSet;

import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JMenuItem;

import org.openbp.common.CollectionUtil;
import org.openbp.common.CommonUtil;
import org.openbp.common.generic.Copyable;
import org.openbp.common.generic.description.DisplayObject;
import org.openbp.common.generic.description.DisplayObjectImpl;
import org.openbp.common.icon.MultiIcon;
import org.openbp.common.listener.BeanListenerSupport;
import org.openbp.common.logger.LogUtil;
import org.openbp.common.rc.ResourceCollection;
import org.openbp.common.rc.ResourceCollectionUtil;
import org.openbp.jaspira.action.keys.KeySequence;
import org.openbp.jaspira.event.JaspiraEventMgr;
import org.openbp.jaspira.gui.plugin.PluginFocusMgr;
import org.openbp.jaspira.plugin.Plugin;

/**
 * Base class for actions within the Jaspria framework.
 * Each action has an optional name, display name and a description.
 * The display will be show as menu item text, the description will be used as tool tip
 * of a component that activates the action.
 *
 * if the {@link #actionPerformed} method is not overriden, it will fire an {@link JaspiraActionEvent}
 * using the name of the action as event name. The source plugin of the event will be the
 * currently focused plugin or (if none) the owner plugin of the action.
 *
 * Actions can contain several icons and descriptions. The small icon is
 * used in Menus. The large icon is used in toolbars.
 *
 * Jaspira actions are also used to build menu and toolbar structures.
 * The type of the action determines what the action represents:
* {@link #TYPE_ACTION} or null: Regular action
* {@link #TYPE_MENU}: Menu (used to hold sub menu items; it doesn't have a real action functionality)
* {@link #TYPE_GROUP}: Menu or toolbar group * * An action can have a menu parent and/or a toolbar parent, which determines where to place * the action in the main menu or the main toolbar.
* Group or menu actions may also have menu or toolbar children. * * @author Stephan Moritz */ public class JaspiraAction extends DisplayObjectImpl implements Action { // TODO Refactor 6: We should split this class in different sub classes e. g. for actions, groups, combos etc. ///////////////////////////////////////////////////////////////////////// // @@ Resource/property Constants ///////////////////////////////////////////////////////////////////////// /** Property id for name */ public static final String PROPERTY_NAME = "name"; /** Property id for display name */ public static final String PROPERTY_DISPLAY_NAME = "displayName"; /** Property id for description */ public static final String PROPERTY_DESCRIPTION = "description"; /** Property id for normal icon */ public static final String PROPERTY_ICON = "icon"; /** Property id for disabled icon */ public static final String PROPERTY_DISABLED_ICON = "disabledicon"; /** Property id for key sequences */ public static final String PROPERTY_SEQUENCE = "sequence"; /** Property id for enabled option */ public static final String PROPERTY_ENABLED = "enabled"; /** Propertyid for selected option */ public static final String PROPERTY_SELECTED = "selected"; /** Property id for priority of the action */ public static final String PROPERTY_PRIO = "prio"; /** Property id for action scope */ public static final String PROPERTY_SCOPE = "scope"; /** Property id for the type of action */ public static final String PROPERTY_TYPE = "type"; /** Property id for menu parent if action has to be displayed in the menu */ public static final String PROPERTY_MENU_PARENT = "menuparent"; /** Property id for toolbar parent if action has to be displayed in teh toolbar */ public static final String PROPERTY_TOOLBAR_PARENT = "toolbarparent"; /** Property id for the names of the Jaspira pages that should display this action in the page menu or toolbar */ public static final String PROPERTY_PAGE_NAMES = "pagenames"; /** Property id for the conditional expression */ public static final String PROPERTY_CONDITION = "condition"; /** Id for the menu root - top level of a menu*/ public static final String MENU_ROOT = "menuroot"; /** Id for the toolbar root - top level of a toolbar */ public static final String TOOLBAR_ROOT = "toolbarroot"; /** Regular action */ public static final String TYPE_ACTION = "action"; /** Combo box action */ public static final String TYPE_COMBO = "combo"; /** Menu (used to hold sub menu items; it doesn't have a real action functionality) */ public static final String TYPE_MENU = "menu"; /** Menu or toolbar group */ public static final String TYPE_GROUP = "group"; /** Delimiter for multiple key sequences */ public static final String KEY_SEQUENCE_DELIM = ","; /** Default priority of an action */ public static final int DFLT_PRIORITY = 50; /** Delimiter to show the mnemonic key - key after delimiter gets mnemonic */ public static final String MNEMONIC_DELIMITER = "_"; /** Resource containing the action properties */ private ResourceCollection actionResourceCollection; /** Toolbar/menu icon */ private MultiIcon icon; /** Disabled version of the icon */ private MultiIcon disabledIcon; /** The position of the mnemonic underscore in the title */ private int mnemonicpos; /** Key sequence for action activation */ private KeySequence [] keySequences; /** Enabled status */ private boolean enabled = true; /** Selected status. */ private boolean selected; /** Priority */ private int priority; /** Conditional expression that determines if the plugin should be active */ private String condition; /** Type of the action ({@link #TYPE_ACTION}/{@link #TYPE_COMBO}/{@link #TYPE_MENU}/{@link #TYPE_GROUP}/null) */ private String type; /** Names of the Jaspira pages that should display this action in the page menu or toolbar */ private String [] pageNames; /** Children of the action in the menu mode : contains JaspiraActions */ private transient SortedSet menuchildren; /** Children of the action in the toolbar mode : contains JaspiraActions */ private transient SortedSet toolbarchildren; /** Action values */ private transient Map values; /** Scope of the event generated by this action (i\.e\. the level to which this event is propagated) */ private int scope; /** Used by the actionmanager to count instances if an action. */ private int counter; ///////////////////////////////////////////////////////////////////////// // @@ Static comparator ///////////////////////////////////////////////////////////////////////// /** Comparator used to order menu entries. */ private static Comparator priorityComparator = new PriorityComparator(); /** * Constructor. * The new action retrieves its properties from the resource of its owner plugin using the given action name. * * @param owner Owner plugin of the action * @param name Action name */ public JaspiraAction(Plugin owner, String name) { this(owner.getPluginResourceCollection(), name); } /** * Constructor. * The new action retrieves its properties from the given resource using the given action name. * * @param res Action resource * @param name Action name */ public JaspiraAction(ResourceCollection res, String name) { super(name); this.actionResourceCollection = res; // Load display name and description from the resource and check for mnemonic ResourceCollectionUtil.loadDisplayObjectFromResource(this, res, name); checkForMnemonic(); // Load the enabled icon this.icon = (MultiIcon) getActionProperty(PROPERTY_ICON); // Load the disabled icon this.disabledIcon = (MultiIcon) getActionProperty(PROPERTY_DISABLED_ICON); // Load the enabled option this.enabled = getActionPropertyBoolean(PROPERTY_ENABLED, true); // Load the selected option this.selected = getActionPropertyBoolean(PROPERTY_SELECTED, false); // Load the type (group, action, ...; default: regular action) this.type = getActionPropertyString(PROPERTY_TYPE, TYPE_ACTION); // Load the priority this.priority = getActionPropertyInt(PROPERTY_PRIO, DFLT_PRIORITY); // Load the condition this.condition = getActionPropertyString(PROPERTY_CONDITION); // Load the scope of the event to generate from the action String scopeStr = getActionPropertyString(PROPERTY_SCOPE); this.scope = Plugin.LEVEL_APPLICATION; if (scopeStr != null) { if (scopeStr.equals("application")) { this.scope = Plugin.LEVEL_APPLICATION; } else if (scopeStr.equals("frame")) { this.scope = Plugin.LEVEL_FRAME; } else if (scopeStr.equals("page")) { this.scope = Plugin.LEVEL_PAGE; } else if (scopeStr.equals("plugin")) { this.scope = Plugin.LEVEL_PLUGIN; } else { // Log as warning LogUtil.warn(getClass(), "Invalid value for scope of action $0 in resource $1.", name, res.getErrorName()); } } // Load multiple sequences String keys = getActionPropertyString(PROPERTY_SEQUENCE); if (keys != null) { StringTokenizer sto = new StringTokenizer(keys, KEY_SEQUENCE_DELIM); keySequences = new KeySequence [sto.countTokens()]; for (int i = 0; sto.hasMoreTokens(); i++) { keySequences [i] = new KeySequence(sto.nextToken()); } } // Parse the names of the Jaspira pages that should display this action in the page menu or toolbar String pageNameStr = getActionPropertyString(PROPERTY_PAGE_NAMES); if (pageNameStr != null) { ArrayList list = new ArrayList(); // Use ',' or ' ' as page name separator StringTokenizer st = new StringTokenizer(pageNameStr, ", ", false); while (st.hasMoreTokens()) { String pageName = st.nextToken(); list.add(pageName); } pageNames = CollectionUtil.toStringArray(list); } } /** * Explicit constructor. * Usually it is preferable to use the resource based constructor. * * @param name The internal name of the object * @param displayName Display name of this object * @param description Description of this object * @param icon Toolbar/menu icon * @param keySequences Key sequences for action activation * @param priority Priority * @param type Type of the action ({@link #TYPE_ACTION}/{@link #TYPE_COMBO}/{@link #TYPE_MENU}/{@link #TYPE_GROUP}/null) */ public JaspiraAction(String name, String displayName, String description, MultiIcon icon, KeySequence [] keySequences, int priority, String type) { super(name, displayName, description); this.icon = icon; this.keySequences = keySequences; this.priority = priority; this.type = type; checkForMnemonic(); } /** * Constructor using the given display object. * * @param obj Display object to copy name, display name and description from */ public JaspiraAction(DisplayObject obj) { try { copyFrom(obj, Copyable.COPY_DEEP); } catch (CloneNotSupportedException e) { // Never happens } this.priority = DFLT_PRIORITY; this.type = TYPE_ACTION; checkForMnemonic(); } ////////////////////////////////////////////////// // @@ Action execution ////////////////////////////////////////////////// /** * Called if the action has been activated. * For actions of the TYPE_ACTION or TYPE_COMBO, the method fires a {@link JaspiraActionEvent} that has the * same name as the action either to the currently focused plugin (if there is one) or * to the global application plugin. * * @param ae Action event */ public void actionPerformed(ActionEvent ae) { if (type.equals(TYPE_ACTION) || type.equals(TYPE_COMBO)) { Plugin focusedPlugin = PluginFocusMgr.getInstance().getFocusedPlugin(); if (focusedPlugin != null) { focusedPlugin.fireEvent(new JaspiraActionEvent(focusedPlugin, getName(), ae, scope)); } else { JaspiraEventMgr.fireGlobalEvent(new JaspiraActionEvent(null, getName(), ae, scope)); } } } ///////////////////////////////////////////////////////////////////////// // @@ component generation ///////////////////////////////////////////////////////////////////////// /** * Constructs a component from this action. * @return Null */ public JComponent toComponent() { return null; } /** * Constructs a tool bar component from this action. * * @return A {@link JaspiraToolbarButton} if the action is a regular action, * a {@link JaspiraToolbar} if the action has toolbar children, null otherwise */ public JComponent toToolBarComponent() { return toToolBarComponent(null); } /** * Constructs a tool bar component from this action, considering the given page name. * The toolbar will contain only those children that match the * given page name (see {@link #matchesPageName}). * * @param currentPageName Name of the Jaspira page to check against or null * @return A {@link JaspiraToolbarButton} if the action is a regular action, * a {@link JaspiraToolbar} if the action has toolbar children, null otherwise */ public JComponent toToolBarComponent(String currentPageName) { if (type.equals(TYPE_ACTION)) { // we are a simple action so return a toolbar button return new JaspiraToolbarButton(this); } else if (type.equals(TYPE_COMBO)) { // Return the selection field return new JaspiraToolbarCombo(this); } else { if (toolbarchildren == null || toolbarchildren.isEmpty()) { // We have no children, so we do not want the menu itself to be shown return null; } // we are a toolbar group - create a subtoolbar and return it. JaspiraToolbar bar = null; for (Iterator it = toolbarchildren.iterator(); it.hasNext();) { JaspiraAction childAction = (JaspiraAction) it.next(); if (childAction == null) continue; if (currentPageName != null && !childAction.matchesPageName(currentPageName)) continue; if (bar == null) { bar = new JaspiraToolbar(); } bar.add(childAction.toToolBarComponent(currentPageName)); } return bar; } } /** * Constructs a menu item from this action. * * @return A {@link JaspiraMenuItem} if the action is a regular action, * a {@link JaspiraMenu} if the action is a menu action and has menu children, null otherwise */ public JMenuItem toMenuItem() { return toMenuItem(null); } /** * Constructs a menu item from this action, considering the given page name. * If the result is a menu, it will contain only those children that match the * given page name (see {@link #matchesPageName}). * * @param currentPageName Name of the Jaspira page to check against or null * @return A {@link JaspiraMenuItem} if the action is a regular action, * a {@link JaspiraMenu} if the action is a menu action and has menu children, null otherwise */ public JMenuItem toMenuItem(String currentPageName) { if (type.equals(TYPE_ACTION)) { // we are a simple action so return a array with only one entry. return new JaspiraMenuItem(this); } else if (type.equals(TYPE_MENU)) { if (menuchildren == null || menuchildren.isEmpty()) { // We have no children, so we do not want the menu itself to be shown return null; } // we are a menu with subentries - create the menu and return it. JaspiraMenu menu = null; for (Iterator it = menuchildren.iterator(); it.hasNext();) { JaspiraAction childAction = (JaspiraAction) it.next(); if (childAction == null) continue; if (currentPageName != null && !childAction.matchesPageName(currentPageName)) continue; if (childAction.getType().equals(TYPE_GROUP)) { if (childAction.getMenuchildren() == null) { // The group is empty, ignore it. continue; } for (Iterator it2 = childAction.getMenuchildren().iterator(); it2.hasNext();) { JaspiraAction childAction2 = (JaspiraAction) it2.next(); if (currentPageName != null && !childAction2.matchesPageName(currentPageName)) continue; JMenuItem menuItem = childAction2.toMenuItem(currentPageName); if (menu == null) { menu = new JaspiraMenu(this); } menu.add(menuItem); } } else { JMenuItem menuItem = childAction.toMenuItem(currentPageName); if (menu == null) { menu = new JaspiraMenu(this); } menu.add(menuItem); } if (it.hasNext()) { if (menu != null) { menu.addSeparator(); } } } return menu; } // Action groups and combos are not represented in a menu should return null... return null; } /** * Checks if an action should be added to the menu or toolbar of this page. * This is the case if the page name ({@link Plugin#getName}) matches the page names * defined for the action ({@link #getPageNames}), in detail if:
* - The action page name list is empty
* - The page name equals an entry in the action page name list * * @param currentPageName Name of the Jaspira page to check against * @return * true The action should be added to this page. * false The action should not appear on this page. */ public boolean matchesPageName(String currentPageName) { if (pageNames == null) return true; if (currentPageName != null) { for (int i = 0; i < pageNames.length; ++i) { if (currentPageName.equals(pageNames [i])) return true; } } return false; } ///////////////////////////////////////////////////////////////////////// // @@ Mnemonic settings ///////////////////////////////////////////////////////////////////////// /** * Checks the Title of the Menu for Mnemonic. */ public void checkForMnemonic() { String title = getDisplayName(); if (title == null) { mnemonicpos = -1; return; } mnemonicpos = title.indexOf(MNEMONIC_DELIMITER); if (mnemonicpos != -1) { // Cut the delimiter from the display name setDisplayName(title.substring(0, mnemonicpos) + title.substring(mnemonicpos + 1)); } } /** * Returns the position of the mnemonic underscore in the display name of * the action. The method returns -1 if no mnemonic is available. * * @return int the position in the display name string or -1 */ public int getMnemonicPos() { return mnemonicpos; } /** * Returns true if the Action has mnemonic. * * @return boolean true if mnemonic is available, false otherwise */ public boolean isMnemonic() { return mnemonicpos != -1; } /** * Returns the mnemonic char of this action. * * @return char mnemonic char */ public char getMnemonicChar() { if (isMnemonic()) { return getDisplayName().charAt(mnemonicpos); } return '\0'; } /** * Gets the resource containing the action properties. */ public ResourceCollection getActionResource() { return actionResourceCollection; } /** * Returns the menu children. * @return The set of child actions or null */ public SortedSet getMenuchildren() { return menuchildren; } /** * Registers an action at this parent. * * @param action the childaction that wants to register */ public void addMenuChild(JaspiraAction action) { if (menuchildren == null) { menuchildren = new TreeSet(priorityComparator); } menuchildren.add(action); } /** * Unregisters an action from this parent. * * @param action the child action that wants to unregister */ protected void removeMenuChild(JaspiraAction action) { if (menuchildren != null) { menuchildren.remove(action); } } /** * Returns the toolbarchildren. * @return Set of toolbar children or null */ public SortedSet getToolbarchildren() { return toolbarchildren; } /** * Registers an action at this parent. * * @param action the childaction that wants to register */ public void addToolbarChild(JaspiraAction action) { if (toolbarchildren == null) { toolbarchildren = new TreeSet(priorityComparator); } toolbarchildren.add(action); } /** * Unregisters an action from this parent. * * @param action the child action that wants to unregister */ protected void removeToolbarChild(JaspiraAction action) { if (toolbarchildren != null) { toolbarchildren.remove(action); } } /** * Gets the names of the Jaspira pages that should display this action in the page menu or toolbar. * @return The list of page names (see JaspiraPage.getName) or null if the action * should appear for all pages */ public String [] getPageNames() { return pageNames; } /** * Sets the names of the Jaspira pages that should display this action in the page menu or toolbar. * @param pageNames The list of page names (see JaspiraPage.getName) or null if the action * should appear for all pages */ public void setPageNames(String [] pageNames) { this.pageNames = pageNames; } /** * Returns the type. * @return The type of the action ({@link #TYPE_ACTION}/{@link #TYPE_COMBO}/{@link #TYPE_MENU}/{@link #TYPE_GROUP}/null) */ public String getType() { return type; } /** * Gets the toolbar/menu icon. */ public MultiIcon getIcon() { return icon; } /** * Sets the toolbar/menu icon. */ public void setIcon(MultiIcon icon) { if (this.icon != icon) { Object old = this.icon; this.icon = icon; firePropertyChange(PROPERTY_ICON, old, icon); } } /** * Gets the disabled version of the icon. */ public MultiIcon getDisabledIcon() { return disabledIcon; } /** * Sets the disabled version of the icon. */ public void setDisabledIcon(MultiIcon disabledIcon) { if (this.disabledIcon != disabledIcon) { Object old = this.disabledIcon; this.disabledIcon = disabledIcon; firePropertyChange(PROPERTY_DISABLED_ICON, old, icon); } } /** * Gets the key sequences for action activation. */ public KeySequence [] getKeySequences() { return keySequences; } /** * Gets the enabled status. */ public boolean isEnabled() { return enabled; } /** * Sets the enabled status. */ public void setEnabled(boolean enabled) { if (this.enabled != enabled) { Boolean old = Boolean.valueOf(this.enabled); this.enabled = enabled; firePropertyChange(PROPERTY_ENABLED, old, Boolean.valueOf(enabled)); } } /** * Returns the selected status. */ public boolean isSelected() { return selected; } /** * Sets a new displayname for the action. * @see org.openbp.common.generic.description.DisplayObjectImpl#setDisplayName(String) */ public void setDisplayName(String displayName) { // Cache the old name String oldValue = getDisplayName(); if (!CommonUtil.equalsNull(displayName, oldValue)) { // Set the displayname in the DisplayObject super.setDisplayName(displayName); // Notify all components firePropertyChange(PROPERTY_DISPLAY_NAME, oldValue, displayName); } } /** * Sets a new description for the action. * @see org.openbp.common.generic.description.DescriptionObjectImpl#setDescription(String) */ public void setDescription(String description) { // Cache the old name String oldValue = getDescription(); if (!CommonUtil.equalsNull(description, oldValue)) { // Set the description in the DisplayObject super.setDescription(description); // Notify all components firePropertyChange(PROPERTY_DESCRIPTION, oldValue, description); } } /** * Sets the selected status. */ public void setSelected(boolean selected) { if (this.selected != selected) { Boolean old = Boolean.valueOf(this.selected); this.selected = selected; firePropertyChange(PROPERTY_SELECTED, old, Boolean.valueOf(selected)); } this.selected = selected; } /** * Gets the priority. */ public int getPriority() { return priority; } /** * Sets the priority. */ public void setPriority(int priority) { this.priority = priority; } /** * Gets the conditional expression that determines if the plugin should be active. */ public String getCondition() { return condition; } /** * Returns the current value of the reference counter. * @return The reference counter determines how many actions of this type * have been created using the {@link ActionMgr} */ public int getCounter() { return counter; } /** * Increases the reference counter of the action. */ public void increaseCounter() { counter++; } /** * Decrease the reference counter of the action. * @return * true There are still references left to this action.
* false The reference counter decreased to 0. */ public boolean decreaseCounter() { return --counter > 0; } ///////////////////////////////////////////////////////////////////////// // @@ Action implementation ///////////////////////////////////////////////////////////////////////// /** * @see javax.swing.Action#getValue(String) */ public Object getValue(String key) { if (values != null) { return values.get(key); } return null; } /** * @see javax.swing.Action#putValue(String, Object) */ public void putValue(String key, Object value) { if (values == null) { values = new HashMap(); } Object oldValue = values.put(key, value); // Pass to property change listener so toolbar/menu components may react on this firePropertyChange(key, oldValue, value); } /** * Clears all action values. */ public void clearValues() { if (values != null) { values.clear(); } } ////////////////////////////////////////////////// // @@ Action property acccess ////////////////////////////////////////////////// /** * Gets an action property, either from the action's property map or from the resource file. * For resource file access, the name of the action and "." will be prepended to the resource key. * * @param key Key of the property * @return The property value or null if not found */ public Object getActionProperty(String key) { Object value = getValue(key); if (value == null && actionResourceCollection != null) { // Try to resolve the value from the resource file StringBuffer sb = new StringBuffer(); if (getName() != null) sb.append(getName()); sb.append('.'); sb.append(key); String propKey = sb.toString(); value = actionResourceCollection.getOptionalObject(propKey); } return value; } /** * Gets an action property of type String. * * @param key Key of the property * @return The property value or null if not found */ public String getActionPropertyString(String key) { Object value = getActionProperty(key); if (value != null && !(value instanceof String)) { System.err.println("Action property " + getName() + "." + key + " is not a string."); return null; } return (String) value; } /** * Gets an action property of type String. * * @param key Key of the property * @param dflt Default value * @return The property value or null if not found */ public String getActionPropertyString(String key, String dflt) { String value = getActionPropertyString(key); if (value == null) value = dflt; return value; } /** * Gets an action property of type boolean. * * @param key Key of the property * @param dflt Default value * @return The property value or null if not found */ public boolean getActionPropertyBoolean(String key, boolean dflt) { Object value = getActionProperty(key); boolean ret = dflt; if (value != null) { if (value instanceof Boolean) { ret = ((Boolean) value).booleanValue(); } else if (value instanceof String) { String s = (String) value; if ("false".equals(s)) { ret = false; } else if ("true".equals(s)) { ret = false; } else { System.err.println("Action property " + getName() + "." + key + " is not a boolean."); } } else { System.err.println("Action property " + getName() + "." + key + " is not a boolean."); } } return ret; } /** * Gets an action property of type int. * * @param key Key of the property * @param dflt Default value * @return The property value or null if not found */ public int getActionPropertyInt(String key, int dflt) { Object value = getActionProperty(key); int ret = dflt; if (value != null) { if (value instanceof Integer) { ret = ((Integer) value).intValue(); } else if (value instanceof String) { try { ret = Integer.parseInt((String) value); } catch (NumberFormatException e) { System.err.println("Action property " + getName() + "." + key + " is not an integer."); } } else { System.err.println("Action property " + getName() + "." + key + " is not an integer."); } } return ret; } ///////////////////////////////////////////////////////////////////////// // @@ Property change support ///////////////////////////////////////////////////////////////////////// /** Listener support object holding the listeners */ private BeanListenerSupport listenerSupport; /** * Supports reporting bound property changes. * This method can be called when a bound property has changed and * will send the appropriate PropertyChangeEvent to any registered * property change listeners. * * @param propertyName Name of the bound property * @param oldValue Old value of the property * @param newValue New value of the property */ protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (listenerSupport != null && listenerSupport.containsListeners(PropertyChangeListener.class) && !CommonUtil.equalsNull(oldValue, newValue)) { listenerSupport.firePropertyChange(new PropertyChangeEvent(this, propertyName, oldValue, newValue)); } } /** * Adds a property change listener to the listener list. * A PropertyChangeEvent will get fired in response to setting a bound property. * The listener is registered for all properties as a WEAK listener, i. e. it may * be garbage-collected if not referenced otherwise.
* ATTENTION: Never add an automatic class (i. e new PropertyChangeListener () { ... }) or an inner * class that is not referenced otherwise as a weak listener to the list. These objects * will be cleared by the garbage collector during the next gc run! * * @param listener The listener to be added */ public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { if (listenerSupport == null) { listenerSupport = new BeanListenerSupport(); } listenerSupport.addWeakListener(PropertyChangeListener.class, listener); } /** * Removes a property change listener from the listener list. * * @param listener The listener to be removed */ public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { if (listenerSupport != null) { listenerSupport.removeListener(PropertyChangeListener.class, listener); } } ///////////////////////////////////////////////////////////////////////// // @@ Inner classes ///////////////////////////////////////////////////////////////////////// /** * Comparator used to sort menus and menu entries according to their * priority and displayname. */ private static class PriorityComparator implements Comparator { /** * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(Object o1, Object o2) { JaspiraAction a1 = (JaspiraAction) o1; JaspiraAction a2 = (JaspiraAction) o2; int result = a1.getPriority() - a2.getPriority(); if (result != 0) { return result; } String n1 = a1.getDisplayName(); if (n1 == null) { n1 = a1.getName(); } String n2 = a2.getDisplayName(); if (n2 == null) { n2 = a2.getName(); } return n1.compareTo(n2); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy