0N/A/*
2362N/A * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/Apackage sun.awt.X11;
0N/A
0N/Aimport java.awt.*;
0N/Aimport java.awt.peer.*;
0N/Aimport java.awt.event.*;
0N/A
5255N/Aimport sun.awt.AWTAccessor;
0N/A
0N/Apublic class XMenuItemPeer implements MenuItemPeer {
0N/A
0N/A /************************************************
0N/A *
0N/A * Data members
0N/A *
0N/A ************************************************/
0N/A
0N/A /*
0N/A * Primary members
0N/A */
0N/A
0N/A /**
0N/A * Window that this item belongs to.
0N/A */
0N/A private XBaseMenuWindow container;
0N/A
0N/A /**
0N/A * Target MenuItem. Note that 'target' member
0N/A * in XWindow is required for dispatching events.
0N/A * This member is only used for accessing its fields
0N/A * and firing ActionEvent & ItemEvent
0N/A */
0N/A private MenuItem target;
0N/A
0N/A /*
0N/A * Mapping to window
0N/A */
0N/A
0N/A /**
0N/A * Rectange occupied by menu item in container's
0N/A * coordinates. Filled by map(...) function from
0N/A * XBaseMenuWindow.map()
0N/A */
0N/A private Rectangle bounds;
0N/A
0N/A /**
0N/A * Point in container's coordinate system used as
0N/A * origin by drawText.
0N/A */
0N/A private Point textOrigin;
0N/A
0N/A /*
0N/A * Size constants
0N/A */
0N/A private final static int SEPARATOR_WIDTH = 20;
0N/A private final static int SEPARATOR_HEIGHT = 5;
0N/A
0N/A /************************************************
0N/A *
0N/A * Text Metrics
0N/A *
0N/A ************************************************/
0N/A
0N/A /**
0N/A * Text metrics are filled in calcTextMetrics function
0N/A * and reset in resetTextMetrics function. Text metrics
0N/A * contain calculated dimensions of various components of
0N/A * menu item.
0N/A */
0N/A private TextMetrics textMetrics;
0N/A
0N/A static class TextMetrics implements Cloneable {
0N/A /*
0N/A * Calculated text size members
0N/A */
0N/A private Dimension textDimension;
0N/A private int shortcutWidth;
0N/A private int textBaseline;
0N/A
0N/A TextMetrics(Dimension textDimension, int shortcutWidth, int textBaseline) {
0N/A this.textDimension = textDimension;
0N/A this.shortcutWidth = shortcutWidth;
0N/A this.textBaseline = textBaseline;
0N/A }
0N/A
0N/A public Object clone() {
0N/A try {
0N/A return super.clone();
0N/A } catch (CloneNotSupportedException ex) {
0N/A throw new InternalError();
0N/A }
0N/A }
0N/A
0N/A Dimension getTextDimension() {
0N/A return this.textDimension;
0N/A }
0N/A
0N/A int getShortcutWidth() {
0N/A return this.shortcutWidth;
0N/A }
0N/A
0N/A int getTextBaseline() {
0N/A return this.textBaseline;
0N/A }
0N/A }
0N/A
0N/A /************************************************
0N/A *
0N/A * Construction
0N/A *
0N/A ************************************************/
0N/A XMenuItemPeer(MenuItem target) {
0N/A this.target = target;
0N/A }
0N/A
0N/A /************************************************
0N/A *
0N/A * Implementaion of interface methods
0N/A *
0N/A ************************************************/
0N/A
0N/A /*
0N/A * From MenuComponentPeer
0N/A */
0N/A public void dispose() {
0N/A //Empty function
0N/A }
0N/A
0N/A public void setFont(Font font) {
0N/A resetTextMetrics();
0N/A repaintIfShowing();
0N/A }
0N/A /*
0N/A * From MenuItemPeer
0N/A */
0N/A public void setLabel(String label) {
0N/A resetTextMetrics();
0N/A repaintIfShowing();
0N/A }
0N/A
0N/A public void setEnabled(boolean enabled) {
0N/A repaintIfShowing();
0N/A }
0N/A
0N/A /**
0N/A * DEPRECATED: Replaced by setEnabled(boolean).
0N/A * @see java.awt.peer.MenuItemPeer
0N/A */
0N/A public void enable() {
0N/A setEnabled( true );
0N/A }
0N/A
0N/A /**
0N/A * DEPRECATED: Replaced by setEnabled(boolean).
0N/A * @see java.awt.peer.MenuItemPeer
0N/A */
0N/A public void disable() {
0N/A setEnabled( false );
0N/A }
0N/A
0N/A /************************************************
0N/A *
0N/A * Access to target's fields
0N/A *
0N/A ************************************************/
0N/A
0N/A MenuItem getTarget() {
0N/A return this.target;
0N/A }
0N/A
0N/A Font getTargetFont() {
0N/A if (target == null) {
93N/A return XWindow.getDefaultFont();
0N/A }
5255N/A return AWTAccessor.getMenuComponentAccessor().getFont_NoClientCode(target);
0N/A }
0N/A
0N/A String getTargetLabel() {
0N/A if (target == null) {
0N/A return "";
0N/A }
5257N/A String label = AWTAccessor.getMenuItemAccessor().getLabel(target);
5257N/A return (label == null) ? "" : label;
0N/A }
0N/A
0N/A boolean isTargetEnabled() {
0N/A if (target == null) {
0N/A return false;
0N/A }
5255N/A return AWTAccessor.getMenuItemAccessor().isEnabled(target);
0N/A }
0N/A
0N/A /**
0N/A * Returns true if item and all its parents are enabled
0N/A * This function is used to fix
0N/A * 6184485: Popup menu is not disabled on XToolkit even when calling setEnabled (false)
0N/A */
0N/A boolean isTargetItemEnabled() {
0N/A if (target == null) {
0N/A return false;
0N/A }
5255N/A return AWTAccessor.getMenuItemAccessor().isItemEnabled(target);
0N/A }
0N/A
0N/A String getTargetActionCommand() {
0N/A if (target == null) {
0N/A return "";
0N/A }
5255N/A return AWTAccessor.getMenuItemAccessor().getActionCommandImpl(target);
0N/A }
0N/A
0N/A MenuShortcut getTargetShortcut() {
0N/A if (target == null) {
0N/A return null;
0N/A }
5255N/A return AWTAccessor.getMenuItemAccessor().getShortcut(target);
0N/A }
0N/A
0N/A String getShortcutText() {
0N/A //Fix for 6180413: shortcuts should not be displayed for any of the menuitems in a popup menu
0N/A if (container == null) {
0N/A return null;
0N/A }
0N/A if (container.getRootMenuWindow() instanceof XPopupMenuPeer) {
0N/A return null;
0N/A }
0N/A MenuShortcut sc = getTargetShortcut();
0N/A //TODO:This can potentially call user code
0N/A return (sc == null) ? null : sc.toString();
0N/A }
0N/A
0N/A
0N/A /************************************************
0N/A *
0N/A * Basic manipulations
0N/A *
0N/A ************************************************/
0N/A
0N/A /**
0N/A * This function is called when filling item vectors
0N/A * in XMenuWindow & XMenuBar. We need it because peers
0N/A * are created earlier than windows.
0N/A * @param container the window that this item belongs to.
0N/A */
0N/A void setContainer(XBaseMenuWindow container) {
0N/A synchronized(XBaseMenuWindow.getMenuTreeLock()) {
0N/A this.container = container;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * returns the window that this item belongs to
0N/A */
0N/A XBaseMenuWindow getContainer() {
0N/A return this.container;
0N/A }
0N/A
0N/A /************************************************
0N/A *
0N/A * Overridable behaviour
0N/A *
0N/A ************************************************/
0N/A
0N/A /**
0N/A * This function should be overriden simply to
0N/A * return false in inherited classes.
0N/A */
0N/A boolean isSeparator() {
0N/A boolean r = (getTargetLabel().equals("-"));
0N/A return r;
0N/A }
0N/A
0N/A /************************************************
0N/A *
0N/A * Utility functions
0N/A *
0N/A ************************************************/
0N/A
0N/A /**
0N/A * Returns true if container exists and is showing
0N/A */
0N/A boolean isContainerShowing() {
0N/A if (container == null) {
0N/A return false;
0N/A }
0N/A return container.isShowing();
0N/A }
0N/A
0N/A /**
0N/A * Repaints item if it is showing
0N/A */
0N/A void repaintIfShowing() {
0N/A if (isContainerShowing()) {
0N/A container.postPaintEvent();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * This function is invoked when the user clicks
0N/A * on menu item.
0N/A * @param when the timestamp of action event
0N/A */
0N/A void action(long when) {
0N/A if (!isSeparator() && isTargetItemEnabled()) {
0N/A XWindow.postEventStatic(new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
0N/A getTargetActionCommand(), when,
0N/A 0));
0N/A }
0N/A }
0N/A /************************************************
0N/A *
0N/A * Text metrics
0N/A *
0N/A ************************************************/
0N/A
0N/A /**
0N/A * Returns text metrics of menu item.
0N/A * This function does not use any locks
0N/A * and is guaranteed to return some value
0N/A * (possibly actual, possibly expired)
0N/A */
0N/A TextMetrics getTextMetrics() {
0N/A TextMetrics textMetrics = this.textMetrics;
0N/A if (textMetrics == null) {
0N/A textMetrics = calcTextMetrics();
0N/A this.textMetrics = textMetrics;
0N/A }
0N/A return textMetrics;
0N/A }
0N/A
0N/A /**
0N/A * Returns dimensions of item's label.
0N/A * This function does not use any locks
0N/A * Returns actual or expired value
0N/A * or null if error occurs
0N/A */
0N/A /*Dimension getTextDimension() {
0N/A TextMetrics textMetrics = this.textMetrics;
0N/A if (textMetrics == null) {
0N/A textMetrics = calcTextMetrics();
0N/A this.textMetrics = textMetrics;
0N/A }
0N/A return (textMetrics != null) ? textMetrics.textDimension : null;
0N/A }*/
0N/A
0N/A /**
0N/A * Returns width of item's shortcut label,
0N/A * 0 if item has no shortcut.
0N/A * The height of shortcut can be deternimed
0N/A * from text dimensions.
0N/A * This function does not use any locks
0N/A * and is guaranteed to return some value
0N/A * (possibly actual, possibly expired)
0N/A */
0N/A /*int getShortcutWidth() {
0N/A TextMetrics textMetrics = this.textMetrics;
0N/A if (textMetrics == null) {
0N/A textMetrics = calcTextMetrics();
0N/A this.textMetrics = textMetrics;
0N/A }
0N/A return (textMetrics != null) ? textMetrics.shortcutWidth : 0;
0N/A }
0N/A
0N/A int getTextBaseline() {
0N/A TextMetrics textMetrics = this.textMetrics;
0N/A if (textMetrics == null) {
0N/A textMetrics = calcTextMetrics();
0N/A this.textMetrics = textMetrics;
0N/A }
0N/A return (textMetrics != null) ? textMetrics.textBaseline : 0;
0N/A }*/
0N/A
0N/A TextMetrics calcTextMetrics() {
0N/A if (container == null) {
0N/A return null;
0N/A }
0N/A if (isSeparator()) {
0N/A return new TextMetrics(new Dimension(SEPARATOR_WIDTH, SEPARATOR_HEIGHT), 0, 0);
0N/A }
0N/A Graphics g = container.getGraphics();
0N/A if (g == null) {
0N/A return null;
0N/A }
0N/A try {
0N/A g.setFont(getTargetFont());
0N/A FontMetrics fm = g.getFontMetrics();
0N/A String str = getTargetLabel();
0N/A int width = fm.stringWidth(str);
0N/A int height = fm.getHeight();
0N/A Dimension textDimension = new Dimension(width, height);
0N/A int textBaseline = fm.getHeight() - fm.getAscent();
0N/A String sc = getShortcutText();
0N/A int shortcutWidth = (sc == null) ? 0 : fm.stringWidth(sc);
0N/A return new TextMetrics(textDimension, shortcutWidth, textBaseline);
0N/A } finally {
0N/A g.dispose();
0N/A }
0N/A }
0N/A
0N/A void resetTextMetrics() {
0N/A textMetrics = null;
0N/A if (container != null) {
0N/A container.updateSize();
0N/A }
0N/A }
0N/A
0N/A /************************************************
0N/A *
0N/A * Mapping utility functions
0N/A *
0N/A ************************************************/
0N/A
0N/A /**
0N/A * Sets mapping of item to window.
0N/A * @param bounds bounds of item in container's coordinates
0N/A * @param textOrigin point for drawString in container's coordinates
0N/A * @see XBaseMenuWindow.map()
0N/A */
0N/A void map(Rectangle bounds, Point textOrigin) {
0N/A this.bounds = bounds;
0N/A this.textOrigin = textOrigin;
0N/A }
0N/A
0N/A /**
0N/A * returns bounds of item that were previously set by map() function
0N/A */
0N/A Rectangle getBounds() {
0N/A return bounds;
0N/A }
0N/A
0N/A /**
0N/A * returns origin of item's text that was previously set by map() function
0N/A */
0N/A Point getTextOrigin() {
0N/A return textOrigin;
0N/A }
0N/A
0N/A}