IDEA-162025 Unexpected focus-effect painting in ComboBox with custom JPanel-based...
[idea/community.git] / platform / util / src / com / intellij / util / ui / JBUI.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.util.ui;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.util.IconLoader;
20 import com.intellij.openapi.util.Pair;
21 import com.intellij.openapi.util.SystemInfo;
22 import com.intellij.ui.border.CustomLineBorder;
23 import com.intellij.util.SystemProperties;
24 import com.intellij.util.ui.components.BorderLayoutPanel;
25 import com.intellij.util.ui.components.ComboBoxCompositeEditor;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
28
29 import javax.swing.*;
30 import javax.swing.border.Border;
31 import javax.swing.border.CompoundBorder;
32 import javax.swing.plaf.UIResource;
33 import java.awt.*;
34
35 /**
36  * @author Konstantin Bulenkov
37  */
38 public class JBUI {
39   private static final Logger LOG = Logger.getInstance("#com.intellij.util.ui.JBUI");
40
41   /**
42    * A default system scale factor.
43    */
44   public static final float SYSTEM_DEF_SCALE = getSystemDefScale();
45
46   private static float scaleFactor;
47
48   static {
49     setScaleFactor(SYSTEM_DEF_SCALE);
50   }
51
52   private static float getSystemDefScale() {
53     if (SystemInfo.isMac) {
54       return 1.0f;
55     }
56
57     if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) {
58       return 1.0f;
59     }
60
61     UIUtil.initSystemFontData();
62     Pair<String, Integer> fdata = UIUtil.getSystemFontData();
63
64     int size;
65     if (fdata != null) {
66       size = fdata.getSecond();
67     } else {
68       size = Fonts.label().getSize();
69     }
70     return size / UIUtil.DEF_SYSTEM_FONT_SIZE;
71   }
72
73   public static void setScaleFactor(float scale) {
74     if (SystemProperties.has("hidpi") && !SystemProperties.is("hidpi")) {
75       scaleFactor = 1.0f;
76       LOG.info("UI scale factor: 1.0");
77       return;
78     }
79
80     if (scale < 1.25f) scale = 1.0f;
81     else if (scale < 1.5f) scale = 1.25f;
82     else if (scale < 1.75f) scale = 1.5f;
83     else if (scale < 2f) scale = 1.75f;
84     else scale = 2.0f;
85
86     if (SystemInfo.isLinux && scale == 1.25f) {
87       //Default UI font size for Unity and Gnome is 15. Scaling factor 1.25f works badly on Linux
88       scale = 1f;
89     }
90     if (scaleFactor == scale) {
91       return;
92     }
93     LOG.info("UI scale factor: " + scale);
94
95     scaleFactor = scale;
96     IconLoader.setScale(scale);
97   }
98
99   public static int scale(int i) {
100     return Math.round(scaleFactor * i);
101   }
102
103   public static int scaleFontSize(int fontSize) {
104     if (scaleFactor == 1.25f) return (int)(fontSize * 1.34f);
105     if (scaleFactor == 1.75f) return (int)(fontSize * 1.67f);
106     return scale(fontSize);
107   }
108
109   public static JBDimension size(int width, int height) {
110     return new JBDimension(width, height);
111   }
112
113   public static JBDimension size(int widthAndHeight) {
114     return new JBDimension(widthAndHeight, widthAndHeight);
115   }
116
117   public static JBDimension size(Dimension size) {
118     if (size instanceof JBDimension) {
119       final JBDimension jbSize = (JBDimension)size;
120       if (jbSize.originalScale == scale(1f)) {
121         return jbSize;
122       }
123       final JBDimension newSize = new JBDimension((int)(jbSize.width / jbSize.originalScale), (int)(jbSize.height / jbSize.originalScale));
124       return size instanceof UIResource ? newSize.asUIResource() : newSize;
125     }
126     return new JBDimension(size.width, size.height);
127   }
128
129   public static JBInsets insets(int top, int left, int bottom, int right) {
130     return new JBInsets(top, left, bottom, right);
131   }
132
133   public static JBInsets insets(int all) {
134     return insets(all, all, all, all);
135   }
136
137   public static JBInsets insets(int topBottom, int leftRight) {
138     return insets(topBottom, leftRight, topBottom, leftRight);
139   }
140
141   public static JBInsets emptyInsets() {
142     return new JBInsets(0, 0, 0, 0);
143   }
144
145   public static JBInsets insetsTop(int t) {
146     return insets(t, 0, 0, 0);
147   }
148
149   public static JBInsets insetsLeft(int l) {
150     return insets(0, l, 0, 0);
151   }
152
153   public static JBInsets insetsBottom(int b) {
154     return insets(0, 0, b, 0);
155   }
156
157   public static JBInsets insetsRight(int r) {
158     return insets(0, 0, 0, r);
159   }
160
161   public static EmptyIcon emptyIcon(int i) {
162     return (EmptyIcon)EmptyIcon.create(scale(i));
163   }
164
165   public static JBDimension emptySize() {
166     return new JBDimension(0, 0);
167   }
168
169   public static float scale(float f) {
170     return f * scaleFactor;
171   }
172
173   public static JBInsets insets(Insets insets) {
174     return JBInsets.create(insets);
175   }
176
177   public static boolean isHiDPI() {
178     return scaleFactor > 1.0f;
179   }
180
181   public static class Fonts {
182     public static JBFont label() {
183       return JBFont.create(UIManager.getFont("Label.font"), false);
184     }
185
186     public static JBFont label(float size) {
187       return label().deriveFont(scale(size));
188     }
189
190     public static JBFont smallFont() {
191       return label().deriveFont(UIUtil.getFontSize(UIUtil.FontSize.SMALL));
192     }
193
194     public static JBFont miniFont() {
195       return label().deriveFont(UIUtil.getFontSize(UIUtil.FontSize.MINI));
196     }
197
198     public static JBFont create(String fontFamily, int size) {
199       return JBFont.create(new Font(fontFamily, Font.PLAIN, size));
200     }
201   }
202
203   public static class Borders {
204     public static JBEmptyBorder empty(int top, int left, int bottom, int right) {
205       return new JBEmptyBorder(top, left, bottom, right);
206     }
207
208     public static JBEmptyBorder empty(int topAndBottom, int leftAndRight) {
209       return empty(topAndBottom, leftAndRight, topAndBottom, leftAndRight);
210     }
211
212     public static JBEmptyBorder emptyTop(int offset) {
213       return empty(offset, 0, 0, 0);
214     }
215
216     public static JBEmptyBorder emptyLeft(int offset) {
217       return empty(0, offset,  0, 0);
218     }
219
220     public static JBEmptyBorder emptyBottom(int offset) {
221       return empty(0, 0, offset, 0);
222     }
223
224     public static JBEmptyBorder emptyRight(int offset) {
225       return empty(0, 0, 0, offset);
226     }
227
228     public static JBEmptyBorder empty() {
229       return empty(0, 0, 0, 0);
230     }
231
232     public static Border empty(int offsets) {
233       return empty(offsets, offsets, offsets, offsets);
234     }
235
236     public static Border customLine(Color color, int top, int left, int bottom, int right) {
237       return new CustomLineBorder(color, insets(top, left, bottom, right));
238     }
239
240     public static Border customLine(Color color, int thickness) {
241       return customLine(color, thickness, thickness, thickness, thickness);
242     }
243
244     public static Border customLine(Color color) {
245       return customLine(color, 1);
246     }
247
248     public static Border merge(@Nullable Border source, @NotNull Border extra, boolean extraIsOutside) {
249       if (source == null) return extra;
250       return new CompoundBorder(extraIsOutside ? extra : source, extraIsOutside? source : extra);
251     }
252   }
253
254   public static class Panels {
255     public static BorderLayoutPanel simplePanel() {
256       return new BorderLayoutPanel();
257     }
258
259     public static BorderLayoutPanel simplePanel(Component comp) {
260       return simplePanel().addToCenter(comp);
261     }
262
263     public static BorderLayoutPanel simplePanel(int hgap, int vgap) {
264       return new BorderLayoutPanel(hgap, vgap);
265     }
266   }
267
268   /**
269    *    JComboBox<String> comboBox = new ComboBox<>();
270    *    comboBox.setEditable(true);
271    *    comboBox.setEditor(JBUI.ComboBox.compositeComboboxEditor(new JTextField("Text Field")));
272    */
273   public static class ComboBox {
274     public static ComboBoxCompositeEditor compositeComboboxEditor  (JComponent ... components) {
275       return new ComboBoxCompositeEditor(components);
276     }
277   }
278 }