JDK-4236438 : JMenu or JPopupMenu that is too long for screen.
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 1999-05-07
  • Updated: 1999-06-24
  • Resolved: 1999-06-24
Related Reports
Duplicate :  
Description

Name: skT88420			Date: 05/07/99


We need to create a menu of countries from different regions.
Sometimes the menu is longer than the screen. It would be nice if
JMenu or JPopupMenu would take care of this automatically with
a "more" feature.

Barring this it would be nice if a few of the methods in JMenu
were protected and not private:
	ensurePopupMenuCreated
	getPopupMenuOrigin.
(Review ID: 57968) 
======================================================================

Comments
EVALUATION You can set the layout manager of a PopupMenu, so it is already possible to avoid a menu which is longer than the screen. getPopupMenuOrigin was already made protected for kestrel
11-06-2004

WORK AROUND Name: skT88420 Date: 05/07/99 Not a full workaround but it does give you a better chance that a long menu will fit on screen. The current implementation (swing 1.1.1 beta2) only will push the menu up or down. The following code will start the menu from the top of the screen if it doesn't fit straight down or straight up. Note this borrows a lot of ideas from the right/left bug: import javax.swing.*; import java.awt.*; /** * A subclass of JMenu which adds a simple heuristic for ensuring * that the popup menu gets placed onscreen. */ public class JMenuPlus extends JMenu { public JMenuPlus(String label) { super(label); } // We override this method just so we can call our version of // getPopupMenuOrigin. It is pretty much just a copy of JMenu.setPopupMenuVisible public void setPopupMenuVisible(boolean b) { if (!isEnabled()) return; boolean isVisible = isPopupMenuVisible(); if (b != isVisible) { // We can't call ensurePopupMenuCreated() since it is private so // we call a method that calls it. (Sneaky huh?). isPopupMenuVisible(); // Set location of popupMenu (pulldown or pullright) // Perhaps this should be dictated by L&F if ((b==true) && isShowing()) { Point p = getPopupMenuOrigin(); getPopupMenu().show(this, p.x, p.y); } else { getPopupMenu().setVisible(false); } } } /** * Compute the origin for the JMenu's popup menu. * * @returns a Point in the coordinate space of the menu instance * which should be used as the origin of the JMenu's popup menu. */ protected Point getPopupMenuOrigin() { int x = 0; int y = 0; JPopupMenu pm = getPopupMenu(); // Figure out the sizes needed to caclulate the menu position Dimension screenSize =Toolkit.getDefaultToolkit().getScreenSize(); Dimension s = getSize(); Dimension pmSize = pm.getSize(); // For the first time the menu is popped up, // the size has not yet been initiated if (pmSize.width==0) { pmSize = pm.getPreferredSize(); } Point position = getLocationOnScreen(); Container parent = getParent(); if (parent instanceof JPopupMenu) { // We are a submenu (pull-right) // if( SwingUtilities.isLeftToRight(this) ) { // Package private. if( true ) { // First determine x: if (position.x+s.width + pmSize.width < screenSize.width) { x = s.width; // Prefer placement to the right } else { x = 0-pmSize.width; // Otherwise place to the left } } else { // First determine x: if (position.x < pmSize.width) { x = s.width; // Prefer placement to the right } else { x = 0-pmSize.width; // Otherwise place to the left } } // Then the y: if (position.y+pmSize.height < screenSize.height) { y = 0; // Prefer dropping down } else { y = s.height-pmSize.height; // Otherwise drop 'up' if(y < 0-position.y) y = 0-position.y; } } else { // We are a toplevel menu (pull-down) // if( SwingUtilities.isLeftToRight(this) ) { // Package private. if( true ) { // First determine the x: if (position.x+pmSize.width < screenSize.width) { x = 0; // Prefer extending to right } else { x = s.width-pmSize.width; // Otherwise extend to left } } else { // First determine the x: if (position.x+s.width < pmSize.width) { x = 0; // Prefer extending to right } else { x = s.width-pmSize.width; // Otherwise extend to left } } // Then the y: if (position.y+s.height+pmSize.height < screenSize.height) { y = s.height; // Prefer dropping down } else { y = 0-pmSize.height; // Otherwise drop 'up' if(y < 0-position.y) y = 0-position.y; } } return new Point(x,y); } } ======================================================================
11-06-2004