/* * Bibliothek - DockingFrames * Library built on Java/Swing, allows the user to "drag and drop" * panels containing any Swing-Component the developer likes to add. * * Copyright (C) 2007 Benjamin Sigg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Benjamin Sigg * benjamin_sigg@gmx.ch * CH - Switzerland */ package bibliothek.gui.dock.action; import java.awt.Component; import java.awt.Point; import java.awt.event.MouseEvent; import javax.swing.event.MouseInputAdapter; import bibliothek.gui.Dockable; import bibliothek.gui.dock.action.popup.ActionPopupMenu; import bibliothek.gui.dock.action.popup.ActionPopupMenuFactory; import bibliothek.gui.dock.action.popup.ActionPopupMenuListener; import bibliothek.gui.dock.control.PopupController; /** * A mouse-listener that may be added to any component. When * the popup-trigger is pressed, a popup menu will appear. This menu * shows a list of {@link DockAction DockActions}. * @author Benjamin Sigg */ public abstract class ActionPopup extends MouseInputAdapter{ /** Whether to check the {@link ActionPopupSuppressor} or not */ private boolean suppressable; /** The menu that is currently shown */ private ActionPopupMenu menu; /** * Constructs a new ActionPopup * @param suppressable whether to check the {@link ActionPopupSuppressor} * before popping up, or not. The suppressor can tell the popup, that it * should not be made visible. */ public ActionPopup( boolean suppressable ){ this.suppressable = suppressable; } /** * Whether this ActionPopup can be suppressed or not. * @return <code>true</code> if this can be suppressed */ public boolean isSuppressable() { return suppressable; } /** * Sets whether to ask the {@link ActionPopupSuppressor} if this menu * is allowed to popup or not. * @param suppressable <code>true</code> if the suppressor is allowed to * suppress this popup */ public void setSuppressable( boolean suppressable ) { this.suppressable = suppressable; } @Override public void mousePressed( MouseEvent e ) { if( e.isPopupTrigger() ){ popup( e ); } } @Override public void mouseReleased( MouseEvent e ) { if( e.isPopupTrigger() ){ popup( e ); } } /** * Tells, whether a popup can be displayed, or not. * @return <code>true</code> if a popup can be displayed, <code>false</code> * otherwise. */ protected abstract boolean isEnabled(); /** * Gets the Dockable to which the actions are linked. * @return The Dockable */ protected abstract Dockable getDockable(); /** * Gets the actions, that will be displayed * @return The actions */ protected abstract DockActionSource getActions(); /** * Gets the source object, the object which is responsible for showing the current menu. * @return the source object, may be <code>null</code> */ protected abstract Object getSource(); /** * Shows the popup of this ActionPopup. This method is normally * invoked by the {@link #mousePressed(MouseEvent) mousePressed} * or the {@link #mouseReleased(MouseEvent) mouseReleased}-method * @param e The {@link MouseEvent} that triggers the popup. The event must not * {@link MouseEvent#isConsumed() consumed} */ protected void popup( MouseEvent e ){ if( isMenuOpen() ) return; if( e.isConsumed() ) return; if( isEnabled() ){ boolean shown = popup( e.getComponent(), e.getX(), e.getY() ); if( shown ){ e.consume(); } } } /** * Tells the exact location where the popup should appear. * @param owner the component which triggered a mouse event * @param location where the user clicked onto <code>owner</code> * @return where to open the menu or <code>null</code> to cancel * the operation */ protected Point getPopupLocation( Component owner, Point location ){ return location; } /** * Gets the factory which should be used for creating new popup menus. * @return the factory, not <code>null</code> */ protected ActionPopupMenuFactory getFactory(){ return getDockable().getController().getPopupController().getPopupMenuFactory(); } /** * Pops up this menu. * @param owner the owner of the menu * @param x x-coordinate * @param y y-coordinate * @return <code>true</code> if the menu is shown */ public boolean popup( Component owner, int x, int y ){ Point location = getPopupLocation( owner, new Point( x, y )); if( location == null ) return false; final Dockable dockable = getDockable(); if( dockable.getController() == null ) return false; PopupController popup = dockable.getController().getPopupController(); if( !popup.isAllowOnMove() && dockable.getController().getRelocator().isOnMove() ) return false; DockActionSource actions = getActions(); if( !popup.isAllowEmptyMenu() && actions.getDockActionCount() == 0 ) return false; if( isSuppressable() && dockable.getController().getPopupSuppressor().suppress( dockable, actions )) return false; final ActionPopupMenu methodMenu = getFactory().createMenu( owner, dockable, actions, getSource() ); if( methodMenu == null ){ return false; } menu = methodMenu; menu.addListener( new ActionPopupMenuListener(){ public void closed( ActionPopupMenu menu ){ if( methodMenu == menu ){ ActionPopup.this.menu = null; } } }); menu.show( owner, location.x, location.y ); return true; } /** * Tells whether this {@link ActionPopup} currently shows a menu. * @return <code>true</code> if a menu is visible, <code>false</code> otherwise */ public boolean isMenuOpen(){ return menu != null; } }