/******************************************************************************* * Copyright (c) 2005-2008 SAS Institute Inc., ILOG S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * SAS Institute Inc. - initial API and implementation * ILOG S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.albireo.core; import java.util.WeakHashMap; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; /** * This class allows you to register SWT popup menus on AWT/Swing components. * <p> * It is customizable through the "replaceable singleton" design pattern. * @see #setMenu(java.awt.Component, boolean, Menu) * @see SwingControl#getMenu(java.awt.Component, int, int, int, int) */ public class SwtPopupRegistry { // -------------------- Static registry of popup menus -------------------- /** * A popup menu specification. */ private static class MenuInfo { // The menu that shall appear. Menu menu; // Whether it also applies to subcomponents (if not overridden). boolean recursive; // Constructor. MenuInfo ( final Menu menu, final boolean recursive ) { this.menu = menu; this.recursive = recursive; } } private final WeakHashMap /* java.awt.Component -> MenuInfo */menuTable = new WeakHashMap (); /** * Returns the registered menu for a given component. * @param component An AWT/Swing component. * @param recursive Whether to look for a recursive or for a non-recursive * specification of a popup menu. * @return A popup menu, or <code>null</code>. */ public Menu getMenu ( final java.awt.Component component, final boolean recursive ) { synchronized ( this.menuTable ) { final MenuInfo mi = (MenuInfo)this.menuTable.get ( component ); if ( mi != null && mi.recursive == recursive ) { return mi.menu; } else { return null; } } } /** * Registers a popup menu for a given component and, optionally, its * subcomponents. * <p> * Note: You can only specify one popup menu on a given component. You * cannot specify a recursive and a non-recursive popup menu simultaneously * on the same component. * @param component An AWT/Swing component. * @param recursive Whether the menu also applies to subcomponents (unless * another popup menu is specified on the subcomponent or * a component in between in the hierarchy). * @param menu A popup menu, or <code>null</code> to clear the previously * specified popup menu. */ public void setMenu ( final java.awt.Component component, final boolean recursive, final Menu menu ) { synchronized ( this.menuTable ) { MenuInfo mi = (MenuInfo)this.menuTable.get ( component ); if ( menu != null ) { if ( mi != null ) { mi.menu = menu; mi.recursive = recursive; } else { mi = new MenuInfo ( menu, recursive ); this.menuTable.put ( component, mi ); } } else { if ( mi != null ) { this.menuTable.remove ( component ); } } } } /** * Searches for a popup menu to be used on a given component. * <p> * The default implementation walks up the component hierarchy, looking * for popup menus registered with {@link #setMenu}. * <p> * This method can be overridden, to achieve dynamic popup menus. * @param component The component on which a popup event was received. * @param x The x coordinate, relative to the component's top left corner, * of the mouse cursor when the event occurred. * @param y The y coordinate, relative to the component's top left corner, * of the mouse cursor when the event occurred. * @param xAbsolute The x coordinate, relative to this control's top left * corner, of the mouse cursor when the event occurred. * @param yAbsolute The y coordinate, relative to this control's top left * corner, of the mouse cursor when the event occurred. */ protected Menu findMenu ( final java.awt.Component component, final int x, final int y, final int xAbsolute, final int yAbsolute ) { assert Display.getCurrent () != null; synchronized ( this.menuTable ) { MenuInfo mi = (MenuInfo)this.menuTable.get ( component ); if ( mi != null ) { // On the component itself, ignore whether recursive or not. return mi.menu; } for ( java.awt.Component parent = component.getParent (); parent != null; parent = parent.getParent () ) { mi = (MenuInfo)this.menuTable.get ( parent ); if ( mi != null ) { if ( mi.recursive ) { return mi.menu; } else { return null; } } } } // not found return null; } // ======================================================================== // Singleton design pattern private static SwtPopupRegistry theRegistry = new SwtPopupRegistry (); /** * Returns the currently active singleton of this class. */ public static SwtPopupRegistry getInstance () { return theRegistry; } /** * Replaces the singleton of this class. * @param instance An instance of this class or of a customized subclass. */ public static void setInstance ( final SwtPopupRegistry instance ) { theRegistry = instance; } }