JDK-4133790 : Motif L+F JCheckBoxMenuItems don't align the text properly
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.0.1
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_2.5.1
  • CPU: sparc
  • Submitted: 1998-04-30
  • Updated: 2005-02-24
  • Resolved: 2005-02-24
Related Reports
Duplicate :  
Description
In a menu with both textual items and check box items the left edges
of the text should be aligned.  In the Motif L+F, the left edge of the
check box is aligned with the left edge of the textual items.

Name: apR10133			Date: 08/16/2001


There is a testcase for this bug:
------------------------ bug4133790.java ---------------------------
import javax.swing.*;

public class bug4133790 {

    public bug4133790() {
	try {
	    UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
	} catch (Exception e) {
	    e.printStackTrace();
	}

	JFrame fr = new JFrame("Test");
	fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	JMenuBar bar = new JMenuBar();
	fr.setJMenuBar(bar);
	
	JMenu menu = new JMenu("Menu");
	bar.add(menu);

	menu.add(new JMenuItem("simple item"));
	menu.add(new JCheckBoxMenuItem("checkbox item"));
	menu.add(new JRadioButtonMenuItem("checkbox item"));

	JMenu submenu = new JMenu("submenu");
	menu.add(submenu);
	submenu.add(new JMenuItem("simple item"));
	submenu.add(new JMenuItem("simple item"));

	JMenu menu2 = new JMenu("Test");
	bar.add(menu2);
	menu2.add(new JMenuItem("simple item"));
	menu2.add(new JMenuItem("simple item"));
	
	fr.setSize(200,200);
	fr.setVisible(true);
    }
    
    public static void main(String[] argv) {
	new bug4133790();
    }
}
----------------------------------------------------------
###@###.###

======================================================================

Comments
EVALUATION looking into a fix. richard.schiavi@Eng 1998-05-29 Name: apR10133 Date: 08/16/2001 The Motif LAF sets the menu item check icon to the Icon with a zero sizes. So the icon's space don't taken into account when we layout this item. The view of menus which contains the checkbox items are differ from menus without it. So the DefaultMenuLayout should check it's content and make it possible to change the check icon rectangle width in particular cases (at layout menu item methos). The Metal LAF has the same problem (menu item check icon is null). If the right behavior is the same as Motif then the fix will be similar to Motif. ###@###.### ====================================================================== Fixed under different BugID. Closing as duplicate. ###@###.### 2005-2-24 16:27:23 GMT
25-09-2004

SUGGESTED FIX Name: apR10133 Date: 08/16/2001 ------- DefaultMenuLayout.java ------- *** /tmp/d5oa4gd Thu Aug 16 15:44:50 2001 --- DefaultMenuLayout.java Thu Aug 16 15:42:26 2001 *************** *** 13,18 **** --- 13,19 ---- import javax.swing.*; import javax.swing.plaf.UIResource; + import java.awt.Component; import java.awt.Container; import java.awt.Dimension; *************** *** 40,43 **** --- 41,75 ---- } return super.preferredLayoutSize(target); } + + public void addLayoutComponent(Component comp, Object constraints) { + if (comp.getClass() == JCheckBoxMenuItem.class) { + isShift = true; + } + } + + protected boolean isShift = false; + + public void layoutContainer(Container target) { + int nChildren = target.getComponentCount(); + for (int i = 0; i < nChildren; i++) { + Component c = target.getComponent(i); + if (c.getClass() == JCheckBoxMenuItem.class || + c.getClass() == JRadioButtonMenuItem.class) { + isShift = true; + break; + } + } + if (isShift) { + for (int i = 0; i < nChildren; i++) { + Component c = target.getComponent(i); + if (c.getClass() == JMenuItem.class || + c.getClass() == JMenu.class) { + JMenuItem item = (JMenuItem)c; + item.putClientProperty("shiftText", new Boolean(true)); + } + } + } + super.layoutContainer(target); + } } ------- MotifGraphicsUtils.java ------- *** /tmp/dsnaGDc Thu Aug 16 15:35:16 2001 --- MotifGraphicsUtils.java Thu Aug 16 14:45:20 2001 *************** *** 34,39 **** --- 34,40 ---- { /* Client Property keys for text and accelerator text widths */ private static final String MAX_ACC_WIDTH = "maxAccWidth"; + private static final String SHIFT_TEXT = "shiftText"; /** * Draws the point (<b>x</b>, <b>y</b>) in the current color. *************** *** 366,371 **** --- 367,381 ---- if (checkIcon != null) { checkIconR.width = checkIcon.getIconWidth(); checkIconR.height = checkIcon.getIconHeight(); + if (checkIconR.width == 0) { + Boolean shiftText = (Boolean) c.getClientProperty(MotifGraphicsUtils.SHIFT_TEXT); + if (shiftText!=null && shiftText.booleanValue()) { + Icon defaultIcon = UIManager.getIcon("CheckBoxMenuItem.checkIcon"); + if (defaultIcon != null) { + checkIconR.width = defaultIcon.getIconWidth(); + } + } + } } else { checkIconR.width = checkIconR.height = 0; ------- BasicMenuItemUI.java ------- *** /tmp/daOaGid Thu Aug 16 15:47:27 2001 --- BasicMenuItemUI.java Thu Aug 16 15:44:56 2001 *************** *** 65,70 **** --- 65,71 ---- /* Client Property keys for text and accelerator text widths */ static final String MAX_TEXT_WIDTH = "maxTextWidth"; static final String MAX_ACC_WIDTH = "maxAccWidth"; + static final String SHIFT_TEXT = "shiftText"; public static ComponentUI createUI(JComponent c) { return new BasicMenuItemUI(); *************** *** 785,790 **** --- 786,798 ---- } else { checkIconRect.width = checkIconRect.height = 0; + Boolean shiftText = (Boolean) menuItem.getClientProperty(BasicMenuItemUI.SHIFT_TEXT); + if (shiftText!=null && shiftText.booleanValue()) { + Icon defaultIcon = UIManager.getIcon("CheckBoxMenuItem.checkIcon"); + if (defaultIcon != null) { + checkIconRect.width = defaultIcon.getIconWidth(); + } + } } /* Initialize the arrowIcon bounds rectangle width & height. ###@###.### ====================================================================== Name: apR10133 Date: 08/16/2001 ====================================================================== Name: apR10133 Date: 08/16/2001 The DefaultMenuLayout's fix is not accurate. It would be more right to change the conditions in the layoutContainer(): public void layoutContainer(Container target) { int nChildren = target.getComponentCount(); for (int i = 0; i < nChildren; i++) { Component c = target.getComponent(i); if (c instanceof JCheckBoxMenuItem || c instanceof JRadioButtonMenuItem) { isShift = true; break; } } if (isShift) { for (int i = 0; i < nChildren; i++) { Component c = target.getComponent(i); if ( c instanceof JMenuItem && !(c instanceof JCheckBoxMenuItem) && !(c instanceof JRadioButtonMenuItem) ) { JMenuItem item = (JMenuItem)c; item.putClientProperty("shiftText", new Boolean(true)); } } } super.layoutContainer(target); } ###@###.### ======================================================================
25-09-2004