popups (context menus, combobox popups) fix under aqua laf: round corners, selection, etc

This commit is contained in:
Alexey Pegov
2010-08-08 15:37:38 +04:00
parent 5b32815bae
commit a5cbc1988b
4 changed files with 199 additions and 23 deletions
@@ -27,11 +27,14 @@ import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.ColoredSideBorder;
import com.intellij.ui.IdeaBlueMetalTheme;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.mac.MacPopupMenuUI;
import com.intellij.ui.plaf.beg.*;
import com.intellij.util.ui.UIUtil;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
@@ -43,6 +46,8 @@ import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
@@ -307,6 +312,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
PopupFactory popupFactory;
final PopupFactory oldFactory = PopupFactory.getSharedInstance();
if(HEAVY_WEIGHT_POPUP.equals(popupWeight)){
popupFactory=new PopupFactory(){
public Popup getPopup(
@@ -316,7 +322,7 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
int y
) throws IllegalArgumentException{
final Point point = fixPopupLocation(contents, x, y);
return new Popup(owner,contents,point.x,point.y){};
return oldFactory.getPopup(owner, contents, point.x, point.y);
}
};
}else if(MEDIUM_WEIGHT_POPUP.equals(popupWeight)){
@@ -328,14 +334,49 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
private Popup createPopup(final Component owner, final Component contents, final int x, final int y) {
final Point point = fixPopupLocation(contents, x, y);
final Popup popup = super.getPopup(owner, contents, point.x, point.y);
return popup;
return oldFactory.getPopup(owner, contents, point.x, point.y);
}
};
}else{
throw new IllegalStateException("unknown value of property -Didea.popup.weight: "+popupWeight);
}
PopupFactory.setSharedInstance(popupFactory);
// update ui for popup menu to get round corners
if (UIUtil.isUnderAquaLookAndFeel()) {
final UIDefaults uiDefaults = UIManager.getLookAndFeelDefaults();
uiDefaults.put("PopupMenuUI", MacPopupMenuUI.class.getCanonicalName());
final Icon icon = getAquaMenuInvertedIcon();
if (icon != null) {
uiDefaults.put("Menu.invertedArrowIcon", icon);
}
}
}
@Nullable
private static Icon getAquaMenuInvertedIcon() {
if (!UIUtil.isUnderAquaLookAndFeel()) return null;
final Icon arrow = (Icon) UIManager.get("Menu.arrowIcon");
if (arrow == null) return null;
try {
final Method method = arrow.getClass().getMethod("getInvertedIcon");
if (method != null) {
method.setAccessible(true);
return (Icon) method.invoke(arrow);
}
return null;
}
catch (NoSuchMethodException e1) {
return null;
}
catch (InvocationTargetException e1) {
return null;
}
catch (IllegalAccessException e1) {
return null;
}
}
private Point fixPopupLocation(final Component contents, final int x, final int y) {
@@ -0,0 +1,112 @@
/*
* Copyright 2000-2010 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.mac;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPopupMenuUI;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* User: spLeaner
*/
public class MacPopupMenuUI extends BasicPopupMenuUI {
static Stroke THREE_PIXEL_STROKE = new BasicStroke(3F);
public MacPopupMenuUI() {
}
public static ComponentUI createUI(final JComponent c) {
return new MacPopupMenuUI();
}
public boolean isPopupTrigger(final MouseEvent event) {
return event.isPopupTrigger();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
}
public void paint(final Graphics g, final JComponent jcomponent) {
if (!(g instanceof Graphics2D)) {
super.paint(g, jcomponent);
return;
}
Graphics2D graphics2d = (Graphics2D)g.create();
Rectangle rectangle = popupMenu.getBounds();
paintRoundRect(graphics2d, rectangle);
clipEdges(graphics2d, rectangle);
graphics2d.dispose();
super.paint(g, jcomponent);
}
private static void paintRoundRect(Graphics2D graphics2d, Rectangle rectangle) {
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2d.setComposite(AlphaComposite.Clear);
graphics2d.setStroke(THREE_PIXEL_STROKE);
graphics2d.drawRoundRect(-2, -2, rectangle.width + 3, rectangle.height + 3, 12, 12);
}
protected void clipEdges(Graphics2D graphics2d, Rectangle rectangle) {
Component component = popupMenu.getInvoker();
if (!(component instanceof JMenu)) return;
Rectangle rectangle1 = component.getBounds();
rectangle1.setLocation(component.getLocationOnScreen());
rectangle.setLocation(popupMenu.getLocationOnScreen());
Point point = new Point((int)rectangle1.getCenterX(), (int)rectangle1.getCenterY());
if (rectangle.contains(point)) return;
graphics2d.setComposite(AlphaComposite.SrcOver);
graphics2d.setColor(popupMenu.getBackground());
Point point1 = new Point((int)rectangle.getCenterX(), (int)rectangle.getCenterY());
boolean flag = point.y <= point1.y;
if (rectangle1.x + rectangle1.width < rectangle.x + 10) {
if (flag) {
graphics2d.fillRect(-2, -2, 8, 8);
return;
}
else {
graphics2d.fillRect(-2, rectangle.height - 6, 8, 8);
return;
}
}
if (rectangle.x + rectangle.width < rectangle1.x + 10) {
if (flag) {
graphics2d.fillRect(rectangle.width - 6, -2, 8, 8);
return;
}
else {
graphics2d.fillRect(rectangle.width - 6, rectangle.height - 6, 8, 8);
return;
}
}
if (rectangle1.y + rectangle1.height < rectangle.y + 10) {
graphics2d.fillRect(-2, -2, rectangle.width + 4, 8);
}
}
}
@@ -23,6 +23,7 @@ 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;
@@ -57,6 +58,8 @@ public class BegMenuItemUI extends BasicMenuItemUI {
@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 static final Border SELECTED_BACKGROUND_PAINTER = (Border) UIManager.get("MenuItem.selectedBackgroundPainter");
/** invoked by reflection */
public static ComponentUI createUI(JComponent component) {
return new BegMenuItemUI();
@@ -108,18 +111,22 @@ public class BegMenuItemUI extends BasicMenuItemUI {
g.setColor(jmenuitem.getBackground());
g.fillRect(0, 0, j1, k1);
if (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected()){
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);
if (UIUtil.isUnderAquaLookAndFeel()) {
SELECTED_BACKGROUND_PAINTER.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);
}
//graphics.setColor(BegResources.r);
//graphics.drawLine(j1 - 1, 0, j1 - 1, k1);
}
g.setColor(color2);
}
@@ -180,11 +187,16 @@ public class BegMenuItemUI extends BasicMenuItemUI {
if (keyStrokeText != null && !keyStrokeText.equals("")){
g.setFont(acceleratorFont);
if (buttonmodel.isEnabled()){
if (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected()){
g.setColor(acceleratorSelectionForeground);
if (UIUtil.isUnderAquaLookAndFeel() && (buttonmodel.isArmed() || (comp instanceof JMenu) && buttonmodel.isSelected())) {
g.setColor(selectionForeground);
}
else{
g.setColor(acceleratorForeground);
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());
}
@@ -19,6 +19,7 @@ import com.intellij.Patches;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.MenuKeyEvent;
import javax.swing.event.MenuKeyListener;
import javax.swing.plaf.ComponentUI;
@@ -43,6 +44,9 @@ public class IdeaMenuUI extends BasicMenuUI{
private static final Rectangle ourIconRect = new Rectangle();
private static final Rectangle ourViewRect = new Rectangle(32767, 32767);
private static final Border SELECTED_BACKGROUND_PAINTER = (Border) UIManager.get("MenuItem.selectedBackgroundPainter");
private static final Icon INVERTED_ARROW_ICON = (Icon) UIManager.get("Menu.invertedArrowIcon");
/** invoked by reflection */
public static ComponentUI createUI(JComponent component) {
return new IdeaMenuUI();
@@ -109,12 +113,17 @@ public class IdeaMenuUI extends BasicMenuUI{
g.setColor(jMenu.getBackground());
g.fillRect(0, 0, jMenu.getWidth(), jMenu.getHeight());
if (buttonmodel.isArmed() || buttonmodel.isSelected()){
g.setColor(selectionBackground);
if (allowedIcon != null){
g.fillRect(k, 0, jMenu.getWidth() - k, jMenu.getHeight());
}else{
g.fillRect(0, 0, jMenu.getWidth(), jMenu.getHeight());
if (UIUtil.isUnderAquaLookAndFeel()) {
SELECTED_BACKGROUND_PAINTER.paintBorder(comp, g, 0, 0, jMenu.getWidth(), jMenu.getHeight());
} else {
g.setColor(selectionBackground);
if (allowedIcon != null) {
g.fillRect(k, 0, jMenu.getWidth() - k, jMenu.getHeight());
}
else {
g.fillRect(0, 0, jMenu.getWidth(), jMenu.getHeight());
g.setColor(selectionBackground);
}
}
}
g.setColor(color2);
@@ -179,7 +188,9 @@ public class IdeaMenuUI extends BasicMenuUI{
}
if (useCheckAndArrow()){
try {
arrowIcon.paintIcon(comp, g, ourArrowIconRect.x, ourArrowIconRect.y);
if (UIUtil.isUnderAquaLookAndFeel() && buttonmodel.isSelected() && INVERTED_ARROW_ICON != null) {
INVERTED_ARROW_ICON.paintIcon(comp, g, ourArrowIconRect.x, ourArrowIconRect.y);
} else arrowIcon.paintIcon(comp, g, ourArrowIconRect.x, ourArrowIconRect.y);
}
catch (NullPointerException npe) {
// GTKIconFactory$MenuArrowIcon.paintIcon since it doesn't expect to be given a null instead of SynthContext