fixed 1px bg color near a selected stripe button on hidpi
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / wm / impl / StripeButtonUI.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.wm.impl;
17
18 import com.intellij.ide.ui.UISettings;
19 import com.intellij.openapi.wm.ToolWindowAnchor;
20 import com.intellij.ui.Gray;
21 import com.intellij.util.ui.JBUI;
22 import com.intellij.util.ui.UIUtil;
23
24 import javax.swing.*;
25 import javax.swing.plaf.ComponentUI;
26 import javax.swing.plaf.basic.BasicGraphicsUtils;
27 import javax.swing.plaf.metal.MetalToggleButtonUI;
28 import java.awt.*;
29 import java.awt.geom.AffineTransform;
30
31 /**
32  * @author Vladimir Kondratyev
33  */
34 public final class StripeButtonUI extends MetalToggleButtonUI{
35   private static final StripeButtonUI ourInstance=new StripeButtonUI();
36
37   private static final Rectangle ourIconRect=new Rectangle();
38   private static final Rectangle ourTextRect=new Rectangle();
39   private static final Rectangle ourViewRect=new Rectangle();
40   private static Insets ourViewInsets = JBUI.emptyInsets();
41
42   private StripeButtonUI(){}
43
44   /** Invoked by reflection */
45   @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "unused"})
46   public static ComponentUI createUI(final JComponent c){
47     return ourInstance;
48   }
49
50   public Dimension getPreferredSize(final JComponent c){
51     final AnchoredButton button=(AnchoredButton)c;
52     final Dimension dim=super.getPreferredSize(button);
53
54     dim.width=(int)(JBUI.scale(4) + dim.width*1.1f);
55     dim.height+= JBUI.scale(2);
56
57     final ToolWindowAnchor anchor=button.getAnchor();
58     if(ToolWindowAnchor.LEFT==anchor||ToolWindowAnchor.RIGHT==anchor){
59       //noinspection SuspiciousNameCombination
60       return new Dimension(dim.height,dim.width);
61     } else{
62       return dim;
63     }
64   }
65
66   public void paint(final Graphics g,final JComponent c){
67     final AnchoredButton button=(AnchoredButton)c;
68
69     final String text=button.getText();
70     final Icon icon=(button.isEnabled()) ? button.getIcon() : button.getDisabledIcon();
71
72     if((icon==null)&&(text==null)){
73       return;
74     }
75
76     final FontMetrics fm=button.getFontMetrics(button.getFont());
77     ourViewInsets=c.getInsets(ourViewInsets);
78
79     ourViewRect.x=ourViewInsets.left;
80     ourViewRect.y=ourViewInsets.top;
81
82     final ToolWindowAnchor anchor=button.getAnchor();
83
84     // Use inverted height & width
85     if(ToolWindowAnchor.RIGHT==anchor||ToolWindowAnchor.LEFT==anchor){
86       ourViewRect.height=c.getWidth()-(ourViewInsets.left+ourViewInsets.right);
87       ourViewRect.width=c.getHeight()-(ourViewInsets.top+ourViewInsets.bottom);
88     } else{
89       ourViewRect.height=c.getHeight()-(ourViewInsets.left+ourViewInsets.right);
90       ourViewRect.width=c.getWidth()-(ourViewInsets.top+ourViewInsets.bottom);
91     }
92
93     ourIconRect.x=ourIconRect.y=ourIconRect.width=ourIconRect.height=0;
94     ourTextRect.x=ourTextRect.y=ourTextRect.width=ourTextRect.height=0;
95
96     final String clippedText=SwingUtilities.layoutCompoundLabel(
97       c,fm,text,icon,
98       button.getVerticalAlignment(),button.getHorizontalAlignment(),
99       button.getVerticalTextPosition(),button.getHorizontalTextPosition(),
100       ourViewRect,ourIconRect,ourTextRect,
101       button.getText()==null ? 0 : button.getIconTextGap()
102     );
103
104     // Paint button's background
105
106     final Graphics2D g2 = (Graphics2D)g.create();
107
108     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
109     g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
110
111     final ButtonModel model=button.getModel();
112     final Color background = button.getBackground();
113     ourIconRect.x -= JBUI.scale(2);
114     ourTextRect.x -= JBUI.scale(2);
115     final int off = 1;
116     if (model.isArmed() && model.isPressed() || model.isSelected() || model.isRollover()) {
117       if (anchor == ToolWindowAnchor.LEFT) g2.translate(-off, 0);
118       if (anchor.isHorizontal()) g2.translate(0, -off);
119       final boolean dark = UIUtil.isUnderDarcula();
120       g2.setColor(dark ? Gray._15.withAlpha(model.isSelected() ? 85: 40) : Gray._85.withAlpha(model.isSelected()? 85: 40));
121       g2.fillRect(0, 0, button.getWidth(), button.getHeight());
122       if (anchor == ToolWindowAnchor.LEFT) g2.translate(off, 0);
123       if (anchor.isHorizontal()) g2.translate(0, off);
124     }
125
126
127     AffineTransform tr=null;
128     if(ToolWindowAnchor.RIGHT==anchor||ToolWindowAnchor.LEFT==anchor){
129       tr=g2.getTransform();
130       if(ToolWindowAnchor.RIGHT==anchor){
131         if(icon != null){ // do not rotate icon
132           //noinspection SuspiciousNameCombination
133           icon.paintIcon(c, g2, ourIconRect.y, ourIconRect.x);
134         }
135         g2.rotate(Math.PI/2);
136         g2.translate(0,-c.getWidth());
137       } else {
138         if(icon != null){ // do not rotate icon
139           //noinspection SuspiciousNameCombination
140           icon.paintIcon(c, g2, ourIconRect.y, c.getHeight() - ourIconRect.x - icon.getIconHeight());
141         }
142         g2.rotate(-Math.PI/2);
143         g2.translate(-c.getHeight(),0);
144       }
145     }
146     else{
147       if(icon!=null){
148         icon.paintIcon(c,g2,ourIconRect.x,ourIconRect.y);
149       }
150     }
151
152     // paint text
153
154     UISettings.setupAntialiasing(g2);
155     if(text!=null){
156       if(model.isEnabled()){
157         if(model.isArmed()&&model.isPressed()||model.isSelected()){
158           g2.setColor(background);
159         } else{
160           g2.setColor(button.getForeground());
161         }
162       } else{
163         g2.setColor(background.darker());
164       }
165       /* Draw the Text */
166       if(model.isEnabled()){
167         /* paint the text normally */
168         g2.setColor(UIUtil.isUnderDarcula() && model.isSelected() ? button.getForeground().brighter() : button.getForeground());
169         BasicGraphicsUtils.drawString(g2,clippedText,button.getMnemonic2(),ourTextRect.x,ourTextRect.y+fm.getAscent());
170       } else{
171         /* paint the text disabled ***/
172         if(model.isSelected()){
173           g2.setColor(c.getBackground());
174         } else{
175           g2.setColor(getDisabledTextColor());
176         }
177         BasicGraphicsUtils.drawString(g2,clippedText,button.getMnemonic2(),ourTextRect.x,ourTextRect.y+fm.getAscent());
178       }
179     }
180     if(ToolWindowAnchor.RIGHT==anchor||ToolWindowAnchor.LEFT==anchor){
181       g2.setTransform(tr);
182     }
183     
184     g2.dispose();
185   }
186 }