| |
| /* |
| * Copyright 2000-2009 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.ui.plaf.beg; |
| |
| import com.intellij.openapi.actionSystem.impl.ActionMenuItem; |
| import com.intellij.openapi.keymap.KeymapUtil; |
| import com.intellij.openapi.util.SystemInfo; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NonNls; |
| |
| import javax.swing.*; |
| import javax.swing.border.Border; |
| import javax.swing.event.MenuDragMouseEvent; |
| import javax.swing.event.MenuDragMouseListener; |
| import javax.swing.event.MouseInputListener; |
| import javax.swing.plaf.ComponentUI; |
| import javax.swing.plaf.basic.BasicGraphicsUtils; |
| import javax.swing.plaf.basic.BasicLookAndFeel; |
| import javax.swing.plaf.basic.BasicMenuItemUI; |
| import java.awt.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.KeyEvent; |
| import java.awt.event.MouseEvent; |
| import java.lang.reflect.Method; |
| |
| /** |
| * @author Eugene Belyaev |
| * @author Vladimir Kondratyev |
| */ |
| public class BegMenuItemUI extends BasicMenuItemUI { |
| private static final Rectangle b = new Rectangle(0, 0, 0, 0); |
| private static final Rectangle j = new Rectangle(); |
| private static final Rectangle d = new Rectangle(); |
| private int myMaxGutterIconWidth; |
| private int a; |
| private static Rectangle i = new Rectangle(); |
| private int k; |
| private int e; |
| private static final Rectangle c = new Rectangle(); |
| private static final Rectangle h = new Rectangle(); |
| private static final Rectangle l = new Rectangle(); |
| private static final Rectangle f = new Rectangle(32767, 32767); |
| @NonNls public static final String PLAY_SOUND_METHOD = "playSound"; |
| @NonNls public static final String AQUA_LOOK_AND_FEEL_CLASS_NAME = "apple.laf.AquaLookAndFeel"; |
| @NonNls public static final String GET_KEY_MODIFIERS_TEXT = "getKeyModifiersText"; |
| |
| private Border myAquaSelectedBackgroundPainter; |
| |
| /** invoked by reflection */ |
| public static ComponentUI createUI(JComponent component) { |
| return new BegMenuItemUI(); |
| } |
| |
| public BegMenuItemUI() { |
| myMaxGutterIconWidth = 18; |
| |
| if (UIUtil.isUnderAquaBasedLookAndFeel() && myAquaSelectedBackgroundPainter == null) { |
| myAquaSelectedBackgroundPainter = (Border) UIManager.get("MenuItem.selectedBackgroundPainter"); |
| } |
| } |
| |
| protected void installDefaults() { |
| super.installDefaults(); |
| final String propertyPrefix = getPropertyPrefix(); |
| Integer integer = UIUtil.getPropertyMaxGutterIconWidth(propertyPrefix); |
| if (integer != null){ |
| myMaxGutterIconWidth = integer.intValue(); |
| } |
| } |
| |
| public void paint(Graphics g, JComponent comp) { |
| UIUtil.applyRenderingHints(g); |
| JMenuItem jmenuitem = (JMenuItem)comp; |
| ButtonModel buttonmodel = jmenuitem.getModel(); |
| int mnemonicIndex = jmenuitem.getDisplayedMnemonicIndex(); |
| Icon icon1 = getIcon(); |
| Icon icon2 = getAllowedIcon(); |
| int j1 = jmenuitem.getWidth(); |
| int k1 = jmenuitem.getHeight(); |
| Insets insets = comp.getInsets(); |
| initBounds(); |
| f.setBounds(0, 0, j1, k1); |
| f.x += insets.left; |
| f.y += insets.top; |
| f.width -= insets.right + f.x; |
| f.height -= insets.bottom + f.y; |
| Font font = g.getFont(); |
| Font font1 = comp.getFont(); |
| g.setFont(font1); |
| FontMetrics fontmetrics = g.getFontMetrics(font1); |
| FontMetrics fontmetrics1 = g.getFontMetrics(acceleratorFont); |
| String keyStrokeText; |
| if (jmenuitem instanceof ActionMenuItem) { |
| keyStrokeText = ((ActionMenuItem)jmenuitem).getFirstShortcutText(); |
| }else{ |
| keyStrokeText = getKeyStrokeText(jmenuitem.getAccelerator()); |
| } |
| String s1 = layoutMenuItem(fontmetrics, jmenuitem.getText(), fontmetrics1, keyStrokeText, icon1, icon2, arrowIcon, jmenuitem.getVerticalAlignment(), jmenuitem.getHorizontalAlignment(), jmenuitem.getVerticalTextPosition(), jmenuitem.getHorizontalTextPosition(), f, l, j, c, h, d, jmenuitem.getText() != null ? defaultTextIconGap : 0, defaultTextIconGap); |
| Color color2 = g.getColor(); |
| if (comp.isOpaque()){ |
| g.setColor(jmenuitem.getBackground()); |
| g.fillRect(0, 0, j1, k1); |
| if (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected()){ |
| if (UIUtil.isUnderAquaLookAndFeel()) { |
| myAquaSelectedBackgroundPainter.paintBorder(comp, g, 0, 0, j1, k1); |
| } else { |
| g.setColor(selectionBackground); |
| if (icon2 != null){ |
| g.fillRect(k, 0, j1 - k, k1); |
| } |
| else{ |
| g.fillRect(0, 0, j1, k1); |
| //graphics.setColor(BegResources.q); |
| //graphics.drawLine(0, 0, 0, k1); |
| g.setColor(selectionBackground); |
| } |
| //graphics.setColor(BegResources.r); |
| //graphics.drawLine(j1 - 1, 0, j1 - 1, k1); |
| } |
| } |
| g.setColor(color2); |
| } |
| if (icon2 != null){ |
| if (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected()){ |
| g.setColor(selectionForeground); |
| } |
| else{ |
| g.setColor(jmenuitem.getForeground()); |
| } |
| if (useCheckAndArrow()){ |
| icon2.paintIcon(comp, g, h.x, h.y); |
| } |
| g.setColor(color2); |
| if (menuItem.isArmed()){ |
| drawIconBorder(g); |
| } |
| } |
| if (icon1 != null){ |
| if (!buttonmodel.isEnabled()){ |
| icon1 = jmenuitem.getDisabledIcon(); |
| } |
| else |
| if (buttonmodel.isPressed() && buttonmodel.isArmed()){ |
| icon1 = jmenuitem.getPressedIcon(); |
| if (icon1 == null){ |
| icon1 = jmenuitem.getIcon(); |
| } |
| } |
| if (icon1 != null){ |
| icon1.paintIcon(comp, g, l.x, l.y); |
| } |
| } |
| if (s1 != null && s1.length() > 0){ |
| if (buttonmodel.isEnabled()){ |
| if (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected()){ |
| g.setColor(selectionForeground); |
| } |
| else{ |
| g.setColor(jmenuitem.getForeground()); |
| } |
| BasicGraphicsUtils.drawStringUnderlineCharAt(g, s1, mnemonicIndex, j.x, j.y + fontmetrics.getAscent()); |
| } |
| else { |
| final Object disabledForeground = UIUtil.getMenuItemDisabledForegroundObject(); |
| if (disabledForeground instanceof Color){ |
| g.setColor((Color)disabledForeground); |
| BasicGraphicsUtils.drawStringUnderlineCharAt(g, s1, mnemonicIndex, j.x, j.y + fontmetrics.getAscent()); |
| } |
| else{ |
| g.setColor(jmenuitem.getBackground().brighter()); |
| BasicGraphicsUtils.drawStringUnderlineCharAt(g, s1, mnemonicIndex, j.x, j.y + fontmetrics.getAscent()); |
| g.setColor(jmenuitem.getBackground().darker()); |
| BasicGraphicsUtils.drawStringUnderlineCharAt(g, s1, mnemonicIndex, j.x - 1, (j.y + fontmetrics.getAscent()) - 1); |
| } |
| } |
| } |
| if (keyStrokeText != null && !keyStrokeText.isEmpty()){ |
| g.setFont(acceleratorFont); |
| if (buttonmodel.isEnabled()){ |
| if (UIUtil.isUnderAquaBasedLookAndFeel() && (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected())) { |
| g.setColor(selectionForeground); |
| } |
| else { |
| if (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected()) { |
| g.setColor(acceleratorSelectionForeground); |
| } |
| else { |
| g.setColor(acceleratorForeground); |
| } |
| } |
| BasicGraphicsUtils.drawString(g, keyStrokeText, 0, c.x, c.y + fontmetrics.getAscent()); |
| } |
| else |
| if (disabledForeground != null){ |
| g.setColor(disabledForeground); |
| BasicGraphicsUtils.drawString(g, keyStrokeText, 0, c.x, c.y + fontmetrics.getAscent()); |
| } |
| else{ |
| g.setColor(jmenuitem.getBackground().brighter()); |
| BasicGraphicsUtils.drawString(g, keyStrokeText, 0, c.x, c.y + fontmetrics.getAscent()); |
| g.setColor(jmenuitem.getBackground().darker()); |
| BasicGraphicsUtils.drawString(g, keyStrokeText, 0, c.x - 1, (c.y + fontmetrics.getAscent()) - 1); |
| } |
| } |
| if (arrowIcon != null){ |
| if (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected()){ |
| g.setColor(selectionForeground); |
| } |
| if (useCheckAndArrow()){ |
| arrowIcon.paintIcon(comp, g, d.x, d.y); |
| } |
| } |
| g.setColor(color2); |
| g.setFont(font); |
| } |
| |
| private String getKeyStrokeText(KeyStroke keystroke) { |
| String s1 = ""; |
| if (keystroke != null){ |
| int j1 = keystroke.getModifiers(); |
| if (j1 > 0){ |
| if (SystemInfo.isMac) { |
| try { |
| Class appleLaf = Class.forName(AQUA_LOOK_AND_FEEL_CLASS_NAME); |
| Method getModifiers = appleLaf.getMethod(GET_KEY_MODIFIERS_TEXT, new Class[] {int.class, boolean.class}); |
| s1 = (String)getModifiers.invoke(appleLaf, new Object[] {new Integer(j1), Boolean.FALSE}); |
| } |
| catch (Exception e) { |
| if (SystemInfo.isMacOSLeopard) { |
| s1 = KeymapUtil.getKeyModifiersTextForMacOSLeopard(j1); |
| } |
| else { |
| s1 = KeyEvent.getKeyModifiersText(j1) + '+'; |
| } |
| } |
| } |
| else { |
| s1 = KeyEvent.getKeyModifiersText(j1) + '+'; |
| } |
| |
| } |
| s1 = s1 + KeyEvent.getKeyText(keystroke.getKeyCode()); |
| } |
| return s1; |
| } |
| |
| private boolean useCheckAndArrow() { |
| if ((menuItem instanceof JMenu) && ((JMenu)menuItem).isTopLevelMenu()){ |
| return false; |
| } |
| return true; |
| } |
| |
| public MenuElement[] getPath() { |
| MenuSelectionManager menuselectionmanager = MenuSelectionManager.defaultManager(); |
| MenuElement amenuelement[] = menuselectionmanager.getSelectedPath(); |
| int i1 = amenuelement.length; |
| if (i1 == 0){ |
| return new MenuElement[0]; |
| } |
| java.awt.Container container = menuItem.getParent(); |
| MenuElement amenuelement1[]; |
| if (amenuelement[i1 - 1].getComponent() == container){ |
| amenuelement1 = new MenuElement[i1 + 1]; |
| System.arraycopy(amenuelement, 0, amenuelement1, 0, i1); |
| amenuelement1[i1] = menuItem; |
| } |
| else{ |
| int j1; |
| for(j1 = amenuelement.length - 1; j1 >= 0; j1--){ |
| if (amenuelement[j1].getComponent() == container){ |
| break; |
| } |
| } |
| amenuelement1 = new MenuElement[j1 + 2]; |
| System.arraycopy(amenuelement, 0, amenuelement1, 0, j1 + 1); |
| amenuelement1[j1 + 1] = menuItem; |
| } |
| return amenuelement1; |
| } |
| |
| public Dimension getMinimumSize(JComponent jcomponent) { |
| return null; |
| } |
| |
| private String layoutMenuItem( |
| FontMetrics fontmetrics, |
| String text, |
| FontMetrics fontmetrics1, |
| String keyStrokeText, |
| Icon icon, |
| Icon checkIcon, |
| Icon arrowIcon, |
| int verticalAlignment, |
| int horizontalAlignment, |
| int verticalTextPosition, |
| int horizontalTextPosition, |
| Rectangle viewRect, |
| Rectangle iconRect, |
| Rectangle textRect, |
| Rectangle acceleratorRect, |
| Rectangle checkIconRect, |
| Rectangle arrowIconRect, |
| int textIconGap, |
| int menuItemGap |
| ) { |
| SwingUtilities.layoutCompoundLabel(menuItem, fontmetrics, text, icon, verticalAlignment, horizontalAlignment, verticalTextPosition, horizontalTextPosition, viewRect, iconRect, textRect, textIconGap); |
| if (keyStrokeText == null || "".equals(keyStrokeText)){ |
| acceleratorRect.width = acceleratorRect.height = 0; |
| } |
| else{ |
| acceleratorRect.width = SwingUtilities.computeStringWidth(fontmetrics1, keyStrokeText); |
| acceleratorRect.height = fontmetrics1.getHeight(); |
| } |
| |
| /* Initialize the checkIcon bounds rectangle's width & height. |
| */ |
| if (useCheckAndArrow()){ |
| if (checkIcon != null){ |
| checkIconRect.width = checkIcon.getIconWidth(); |
| checkIconRect.height = checkIcon.getIconHeight(); |
| }else{ |
| checkIconRect.width = checkIconRect.height = 0; |
| } |
| |
| /* Initialize the arrowIcon bounds rectangle width & height. |
| */ |
| if (arrowIcon != null){ |
| arrowIconRect.width = arrowIcon.getIconWidth(); |
| arrowIconRect.height = arrowIcon.getIconHeight(); |
| }else{ |
| arrowIconRect.width = arrowIconRect.height = 0; |
| } |
| textRect.x += myMaxGutterIconWidth; |
| iconRect.x += myMaxGutterIconWidth; |
| } |
| textRect.x += menuItemGap; |
| iconRect.x += menuItemGap; |
| Rectangle labelRect = iconRect.union(textRect); |
| |
| // Position the Accelerator text rect |
| |
| acceleratorRect.x += viewRect.width - arrowIconRect.width - menuItemGap - acceleratorRect.width; |
| acceleratorRect.y = (viewRect.y + viewRect.height / 2) - acceleratorRect.height / 2; |
| |
| // Position the Check and Arrow Icons |
| |
| if (useCheckAndArrow()){ |
| arrowIconRect.x += viewRect.width - arrowIconRect.width; |
| arrowIconRect.y = (viewRect.y + labelRect.height / 2) - arrowIconRect.height / 2; |
| if (checkIcon != null){ |
| checkIconRect.y = (viewRect.y + labelRect.height / 2) - checkIconRect.height / 2; |
| checkIconRect.x += (viewRect.x + myMaxGutterIconWidth / 2) - checkIcon.getIconWidth() / 2; |
| a = viewRect.x; |
| e = (viewRect.y + labelRect.height / 2) - myMaxGutterIconWidth / 2; |
| k = viewRect.x + myMaxGutterIconWidth + 2; |
| } |
| else{ |
| checkIconRect.x = checkIconRect.y = 0; |
| } |
| } |
| return text; |
| } |
| |
| private Icon getIcon() { |
| Icon icon = menuItem.getIcon(); |
| if (icon != null && getAllowedIcon() != null){ |
| icon = null; |
| } |
| return icon; |
| } |
| |
| public Dimension getPreferredSize(JComponent comp) { |
| JMenuItem jmenuitem = (JMenuItem)comp; |
| Icon icon1 = getIcon(); |
| Icon icon2 = getAllowedIcon(); |
| String text = jmenuitem.getText(); |
| String keyStrokeText; |
| if (jmenuitem instanceof ActionMenuItem) { |
| keyStrokeText = ((ActionMenuItem)jmenuitem).getFirstShortcutText(); |
| }else{ |
| keyStrokeText = getKeyStrokeText(jmenuitem.getAccelerator()); |
| } |
| Font font = jmenuitem.getFont(); |
| FontMetrics fontmetrics = comp.getFontMetrics(font); |
| FontMetrics fontmetrics1 = comp.getFontMetrics(acceleratorFont); |
| initBounds(); |
| layoutMenuItem(fontmetrics, text, fontmetrics1, keyStrokeText, icon1, icon2, arrowIcon, jmenuitem.getVerticalAlignment(), jmenuitem.getHorizontalAlignment(), jmenuitem.getVerticalTextPosition(), jmenuitem.getHorizontalTextPosition(), f, l, j, c, h, d, text != null ? defaultTextIconGap : 0, defaultTextIconGap); |
| i.setBounds(j); |
| i = SwingUtilities.computeUnion(l.x, l.y, l.width, l.height, i); |
| if (!(keyStrokeText == null || "".equals(keyStrokeText))){ |
| i.width += c.width; |
| i.width += 7 * defaultTextIconGap; |
| } |
| if (useCheckAndArrow()){ |
| i.width += myMaxGutterIconWidth; |
| i.width += defaultTextIconGap; |
| i.width += defaultTextIconGap; |
| i.width += d.width; |
| } |
| i.width += 2 * defaultTextIconGap; |
| Insets insets = jmenuitem.getInsets(); |
| if (insets != null){ |
| i.width += insets.left + insets.right; |
| i.height += insets.top + insets.bottom; |
| } |
| if (i.width % 2 == 0){ |
| i.width++; |
| } |
| if (i.height % 2 == 0){ |
| i.height++; |
| } |
| return i.getSize(); |
| } |
| |
| private void drawIconBorder(Graphics g) { |
| /* |
| int i1 = a - 1; |
| int j1 = e - 2; |
| int k1 = i1 + myMaxGutterIconWidth + 1; |
| int l1 = j1 + myMaxGutterIconWidth + 4; |
| g.setColor(BegResources.m); |
| g.drawLine(i1, j1, i1, l1); |
| g.drawLine(i1, j1, k1, j1); |
| g.setColor(BegResources.j); |
| g.drawLine(k1, j1, k1, l1); |
| g.drawLine(i1, l1, k1, l1); |
| */ |
| } |
| |
| private void initBounds() { |
| l.setBounds(b); |
| j.setBounds(b); |
| c.setBounds(b); |
| h.setBounds(b); |
| d.setBounds(b); |
| f.setBounds(0, 0, 32767, 32767); |
| i.setBounds(b); |
| } |
| |
| private Icon getAllowedIcon() { |
| Icon icon = menuItem.isEnabled() ? menuItem.getIcon() : menuItem.getDisabledIcon(); |
| if (icon != null && icon.getIconWidth() > myMaxGutterIconWidth){ |
| icon = null; |
| } |
| return icon; |
| } |
| |
| public Dimension getMaximumSize(JComponent comp) { |
| return null; |
| } |
| |
| public void update(Graphics g, JComponent comp) { |
| paint(g, comp); |
| } |
| |
| /** Copied from BasicMenuItemUI */ |
| @SuppressWarnings({"HardCodedStringLiteral"}) |
| private boolean isInternalFrameSystemMenu(){ |
| String actionCommand=menuItem.getActionCommand(); |
| if( |
| ("Close".equals(actionCommand))|| |
| ("Minimize".equals(actionCommand))|| |
| ("Restore".equals(actionCommand))|| |
| ("Maximize".equals(actionCommand)) |
| ){ |
| return true; |
| } else{ |
| return false; |
| } |
| } |
| |
| /** Copied from BasicMenuItemUI */ |
| private void doClick(MenuSelectionManager msm,MouseEvent e) { |
| // Auditory cue |
| if(!isInternalFrameSystemMenu()){ |
| @NonNls ActionMap map=menuItem.getActionMap(); |
| if(map!=null){ |
| Action audioAction=map.get(getPropertyPrefix()+".commandSound"); |
| if(audioAction!=null){ |
| // pass off firing the Action to a utility method |
| BasicLookAndFeel lf=(BasicLookAndFeel)UIManager.getLookAndFeel(); |
| // It's a hack. The method BasicLookAndFeel.playSound has protected access, so |
| // it's imposible to mormally invoke it. |
| try { |
| Method playSoundMethod=BasicLookAndFeel.class.getDeclaredMethod(PLAY_SOUND_METHOD,new Class[]{Action.class}); |
| playSoundMethod.setAccessible(true); |
| playSoundMethod.invoke(lf,new Object[]{audioAction}); |
| } catch(Exception ignored) {} |
| } |
| } |
| } |
| // Visual feedback |
| if(msm==null){ |
| msm=MenuSelectionManager.defaultManager(); |
| } |
| msm.clearSelectedPath(); |
| ((ActionMenuItem)menuItem).fireActionPerformed( |
| new ActionEvent( |
| menuItem, |
| ActionEvent.ACTION_PERFORMED, |
| null, |
| e.getWhen(), |
| e.getModifiers() |
| ) |
| ); |
| } |
| |
| protected MouseInputListener createMouseInputListener(JComponent c){ |
| return new MyMouseInputHandler(); |
| } |
| |
| private class MyMouseInputHandler extends MouseInputHandler{ |
| public void mouseReleased(MouseEvent e){ |
| MenuSelectionManager manager=MenuSelectionManager.defaultManager(); |
| Point p=e.getPoint(); |
| if(p.x>=0&&p.x<menuItem.getWidth()&&p.y>=0&&p.y<menuItem.getHeight()){ |
| doClick(manager,e); |
| } else{ |
| manager.processMouseEvent(e); |
| } |
| } |
| } |
| |
| protected MenuDragMouseListener createMenuDragMouseListener(JComponent c){ |
| return new MyMenuDragMouseHandler(); |
| } |
| |
| private class MyMenuDragMouseHandler implements MenuDragMouseListener { |
| public void menuDragMouseEntered(MenuDragMouseEvent e){} |
| |
| public void menuDragMouseDragged(MenuDragMouseEvent e){ |
| MenuSelectionManager manager=e.getMenuSelectionManager(); |
| MenuElement path[]=e.getPath(); |
| manager.setSelectedPath(path); |
| } |
| |
| public void menuDragMouseExited(MenuDragMouseEvent e){} |
| |
| public void menuDragMouseReleased(MenuDragMouseEvent e){ |
| MenuSelectionManager manager=e.getMenuSelectionManager(); |
| Point p=e.getPoint(); |
| if(p.x>=0&&p.x<menuItem.getWidth()&& |
| p.y>=0&&p.y<menuItem.getHeight()){ |
| doClick(manager,e); |
| } else{ |
| manager.clearSelectedPath(); |
| } |
| } |
| } |
| } |