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

org.openide.util.actions.SystemAction Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
 * Other names may be trademarks of their respective owners.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */

package org.openide.util.actions;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPopupMenu;
import javax.swing.JToolBar;
import org.openide.util.HelpCtx;
import org.openide.util.ImageUtilities;
import org.openide.util.SharedClassObject;
import org.openide.util.Utilities;

/**
* A base class for user-visible actions.
* 

* Implements the Swing {@link Action} interface to enable use * with the Swing action model. *

An action class is a singleton, i.e. should generally contain no instance state. * Rather, subclassing and use of abstract protected methods should be used * to create variants of the action. *

While it is possible to subclass this class directly--for example, if your "action" * is really a placeholder for a popup menu that shows other actions--most people will * prefer to use one of the subclasses, which are more convenient. * * @author Ian Formanek, Jaroslav Tulach */ public abstract class SystemAction extends SharedClassObject implements Action, HelpCtx.Provider { private static final Logger LOG = Logger.getLogger(SystemAction.class.getName()); /** Name of property indicating whether or not the action is enabled. */ public static final String PROP_ENABLED = "enabled"; // NOI18N /** Name of property for the action's display icon. */ public static final String PROP_ICON = "icon"; // NOI18N /** Name of property for the action's display icon, if textual. */ private static final String PROP_ICON_TEXTUAL = "iconTextual"; // NOI18N private static final Set relativeIconResourceClasses = new HashSet(200); // Matches NB 3.4 w/ openide-compat.jar; see #26491 private static final long serialVersionUID = -8361232596876856810L; /** Obtain a singleton instance of the action with a specified class. * If there already is a instance then it is returned, otherwise * a new one is created. * * @param actionClass the class of the action to find * @return the singleton action instance * @exception ClassCastException if the class is not SystemAction * @exception IllegalArgumentException if the instance cannot be created */ public static T get(Class actionClass) { return findObject(actionClass, true); } /** Get a human presentable name of the action. * This may be * presented as an item in a menu. *

Using the normal menu presenters, an included ampersand * before a letter will be treated as the name of a mnemonic. * @return the name of the action */ public abstract String getName(); /** Get a help context for the action. * @return the help context for this action */ public abstract HelpCtx getHelpCtx(); /** Test whether the action is currently enabled. * @return true if so */ public boolean isEnabled() { return getProperty(PROP_ENABLED).equals(Boolean.TRUE); } /** Set whether the action should be enabled. * @param value true to enable it */ public void setEnabled(boolean value) { putProperty(PROP_ENABLED, value ? Boolean.TRUE : Boolean.FALSE, true); } /** Set a property in the singleton. This property is common for all instances * of the same class. * * @param name the name of the property * @param value the value */ public final void putValue(String name, Object value) { putProperty(name, value, true); // Could handle putValue (SMALL_ICON, ImageIcon icon) but not // really that important. } /** Get a property in the singleton. Values are shared among all instances of the same class. * The special tokens {@link Action#NAME}, {@link Action#SMALL_ICON} and "iconBase" are also recognized * and delegated to {@link #getName}, {@link #getIcon} and {@link #iconResource} resp. * @param name the name of the property * @return the value */ public final Object getValue(String name) { if ("iconBase".equals(name)) { // NOI18N return iconResource(); } Object val = getProperty(name); if (val == null) { if (NAME.equals(name)) { val = getName(); } else if (SMALL_ICON.equals(name)) { val = getIcon(); } } return val; } /** Actually perform the action. * Specified in {@link java.awt.event.ActionListener#actionPerformed}. *

In some cases, the implementation may have an empty body, * if the presenters handle the performing of the action in a different way * than by calling this method. *

Since 4.11, will be performed directly in the event thread. * @param ev the event triggering the action */ public abstract void actionPerformed(ActionEvent ev); /** Initialize the action. * The default implementation just enabled it. */ @Override protected void initialize() { putProperty(PROP_ENABLED, Boolean.TRUE); super.initialize(); } /** Indicate whether action state should be cleared after the last action of this class is deleted. * @return false in the default implementation */ @Override protected boolean clearSharedData() { return false; } /** Set the action's display icon. * @param icon the icon */ public final void setIcon(Icon icon) { putProperty(PROP_ICON, icon, true); putProperty(PROP_ICON_TEXTUAL, icon); } /** Get the action's display icon. * @return the icon * @throws IllegalStateException if an icon could not be created */ public final Icon getIcon() { return getIcon(false); } /** Get the action's display icon, possibly creating a text label. * @param createLabel if true, create a textual icon if otherwise there * would be none; if false, create a blank icon * @return an icon * @throws IllegalStateException if an icon could not be created */ public final Icon getIcon(boolean createLabel) { synchronized (getLock()) { Icon img = (Icon) getProperty(createLabel ? PROP_ICON_TEXTUAL : PROP_ICON); if (img == null) { // create the icon from the resource String resName = iconResource(); if (resName != null) { if (resName.indexOf('/') == -1) { // Old action that used a relative path to the icon. // (If it used a relative path going down a directory, tough luck. // It was never documented that you could use relative paths. // apisupport templates did it, but they put icons in the same dir.) String clazz = getClass().getName(); URL u = getClass().getResource(resName); if (u != null) { img = new ImageIcon(u); if (relativeIconResourceClasses.add(clazz)) { LOG.warning("Deprecated relative path in " + clazz + ".iconResource (cf. #20072)"); } } else { LOG.warning("No such icon from " + clazz + ": " + resName); } } else { // Hopefully an absolute path, but again (#26887) might be relative. Image i = ImageUtilities.loadImage(resName, true); if (i != null) { // OK, the normal case. img = new ImageIcon(i); } else { // Check for an old-style relative path. URL u = getClass().getResource(resName); String clazz = getClass().getName(); if (u != null) { // OK, but warn. img = new ImageIcon(u); if (relativeIconResourceClasses.add(clazz)) { LOG.warning("Deprecated relative path in " + clazz + ".iconResource (cf. #26887)"); } } else { // Really can't find it. LOG.warning("No such icon from " + clazz + ": " + resName); } } } putProperty(PROP_ICON, img); putProperty(PROP_ICON_TEXTUAL, img); } } if (img == null) { if (createLabel) { String text = getName(); if (text.endsWith("...")) { // NOI18N text = text.substring(0, text.length() - 3); } text = text.trim(); int ampr = text.indexOf('&'); if (ampr != -1) { text = new StringBuffer(text).deleteCharAt(ampr).toString(); } img = new ComponentIcon(new JLabel(text)); putProperty(PROP_ICON_TEXTUAL, img); } else { putProperty(PROP_ICON, null); } } return img; } } /** Specify the proper resource name for the action's icon. * May be overridden by subclasses; the default is to have no icon. * Typically this should be a 16x16 color GIF. * Do not use relative paths nor an initial slash. * If e.g. myIcon.gif is accompanied with myIcon_pressed.gif, myIcon_disabled.gif * and/or myIcon_rollover.gif these images are used to call methods on JButton.setPressedIcon(), * JButton.setDisabledIcon() and/or JButton.setRolloverIcon() with appropriate images. * Please check Actions.connect for * additional info how this is achieved (using special "iconBase" key for getValue). * As of APIs version 3.24, this path will be used for a localized search automatically. * If you do not want an icon, do not override this to return a blank icon. Leave it null, * but call putValue("noIconInMenu", Boolean.TRUE) to make sure that no extra space is allotted for an icon in the menu item. * @return the resource name for the icon, e.g. com/mycom/mymodule/myIcon.gif; or null to have no icon (make a text label) */ protected String iconResource() { return null; } /** Create the default toolbar representation of an array of actions. * Null items in the array will add a separator to the toolbar. * * @param actions actions to show in the generated toolbar * @return a toolbar instance displaying them */ public static JToolBar createToolbarPresenter(SystemAction[] actions) { JToolBar p = new JToolBar(); for (SystemAction action : actions) { if (action == null) { p.addSeparator(); } else if (action instanceof Presenter.Toolbar) { p.add(((Presenter.Toolbar) action).getToolbarPresenter()); } } return p; } /** Concatenate two arrays of actions. * @param actions1 first array of actions to link * @param actions2 second array of actions to link * @return an array of both sets of actions in the same order */ public static SystemAction[] linkActions(SystemAction[] actions1, SystemAction[] actions2) { List l = new ArrayList(Arrays.asList(actions1)); l.addAll(Arrays.asList(actions2)); return l.toArray(actions1); } /** Create the default popup menu representation of an array of actions. * @param actions actions to show in the generated menu * @return a popup menu displaying them * * @deprecated Use {@link org.openide.util.Utilities#actionsToPopup} */ @Deprecated public static JPopupMenu createPopupMenu(SystemAction[] actions) { return Utilities.actionsToPopup(actions, Utilities.actionsGlobalContext()); } /** Icon based on a component (such as a text label). * Just draws that component as an image. */ private static class ComponentIcon extends ImageIcon { private JComponent comp; private BufferedImage image; /** Create an icon. * @param comp a component, which must be unattached to a container * and should not be used for other purposes */ public ComponentIcon(JComponent comp) { if (comp.getParent() != null) { throw new IllegalArgumentException(); } this.comp = comp; Dimension size = comp.getPreferredSize(); // Careful! If you have e.g. a JLabel with empty text, width = 0 => exceptions. // Must make sure it is at least a reasonable size. comp.setSize(Math.max(size.width, 16), Math.max(size.height, 16)); } @Override protected void loadImage(Image i) { } @Override public void paintIcon(Component c, Graphics g, int x, int y) { // When enabled, tracks color choices of container: comp.setBackground(c.getBackground()); comp.setForeground(c.getForeground()); Graphics clip = g.create(x, y, getIconWidth(), getIconHeight()); comp.paint(clip); } @Override public int getIconWidth() { return comp.getWidth(); } @Override public int getIconHeight() { return comp.getHeight(); } // Needed because this is called directly from e.g. // AbstractButton.getDisabledIcon to pass to GrayFilter, // rather than going through the Icon interface. @Override public Image getImage() { if (image == null) { image = new BufferedImage(getIconWidth(), getIconHeight(), BufferedImage.TYPE_INT_ARGB); // [PENDING] this is obviously ugly, but how should we decide what is the // default fg for the Main Window toolbar area? Background is irrelevant, // since we use alpha channel. But have to guess at the foreground. comp.setForeground(Color.black); comp.paint(image.getGraphics()); } return image; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy