2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com
.intellij
.util
.ui
;
18 import com
.intellij
.openapi
.Disposable
;
19 import com
.intellij
.openapi
.diagnostic
.Logger
;
20 import com
.intellij
.openapi
.util
.Disposer
;
21 import com
.intellij
.openapi
.util
.IconLoader
;
22 import com
.intellij
.openapi
.util
.Key
;
23 import com
.intellij
.openapi
.util
.SystemInfo
;
24 import com
.intellij
.openapi
.util
.text
.StringUtil
;
25 import com
.intellij
.ui
.SideBorder
;
26 import com
.intellij
.util
.ArrayUtil
;
27 import com
.intellij
.util
.ReflectionUtil
;
28 import org
.jetbrains
.annotations
.NonNls
;
29 import org
.jetbrains
.annotations
.NotNull
;
30 import org
.jetbrains
.annotations
.Nullable
;
31 import org
.jetbrains
.annotations
.TestOnly
;
34 import javax
.swing
.text
.html
.HTMLEditorKit
;
35 import javax
.swing
.text
.html
.StyleSheet
;
36 import javax
.swing
.border
.Border
;
37 import javax
.swing
.border
.LineBorder
;
38 import javax
.swing
.plaf
.ProgressBarUI
;
39 import javax
.swing
.plaf
.basic
.BasicTreeUI
;
40 import javax
.swing
.tree
.TreePath
;
42 import java
.awt
.event
.*;
43 import java
.lang
.reflect
.Field
;
44 import java
.lang
.reflect
.Method
;
45 import java
.util
.List
;
48 import java
.util
.TreeSet
;
49 import java
.util
.concurrent
.BlockingQueue
;
50 import java
.util
.concurrent
.LinkedBlockingQueue
;
51 import java
.util
.regex
.Pattern
;
57 private static final Logger LOG
= Logger
.getInstance("#com.intellij.util.ui.UIUtil");
58 @NonNls public static final String HTML_MIME
= "text/html";
59 public static final char MNEMONIC
= 0x1B;
60 @NonNls public static final String JSLIDER_ISFILLED
= "JSlider.isFilled";
61 @NonNls public static final String ARIAL_FONT_NAME
= "Arial";
62 @NonNls public static final String TABLE_FOCUS_CELL_BACKGROUND_PROPERTY
= "Table.focusCellBackground";
65 private static final Color ACTIVE_COLOR
= new Color(160, 186, 213);
66 private static final Color INACTIVE_COLOR
= new Color(128, 128, 128);
67 private static final Color SEPARATOR_COLOR
= INACTIVE_COLOR
.brighter();
68 public static final Pattern CLOSE_TAG_PATTERN
= Pattern
.compile("<\\s*([^<>/ ]+)([^<>]*)/\\s*>", Pattern
.CASE_INSENSITIVE
);
70 @NonNls public static final String FOCUS_PROXY_KEY
= "isFocusProxy";
72 public static Key
<Integer
> KEEP_BORDER_SIDES
= Key
.create("keepBorderSides");
77 public static boolean isReallyTypedEvent(KeyEvent e
) {
78 char c
= e
.getKeyChar();
79 if (!(c
>= 0x20 && c
!= 0x7F)) return false;
81 int modifiers
= e
.getModifiers();
82 if (SystemInfo
.isMac
) {
83 return !e
.isMetaDown() && !e
.isControlDown();
86 return (modifiers
& ActionEvent
.ALT_MASK
) == (modifiers
& ActionEvent
.CTRL_MASK
);
89 public static void setEnabled(Component component
, boolean enabled
, boolean recursively
) {
90 component
.setEnabled(enabled
);
91 if (recursively
&& enabled
== component
.isEnabled()) {
92 if (component
instanceof Container
) {
93 final Container container
= (Container
)component
;
94 final int subComponentCount
= container
.getComponentCount();
95 for (int i
= 0; i
< subComponentCount
; i
++) {
96 setEnabled(container
.getComponent(i
), enabled
, recursively
);
103 public static void drawLine(Graphics g
, int x1
, int y1
, int x2
, int y2
) {
104 g
.drawLine(x1
, y1
, x2
, y2
);
107 public static void setActionNameAndMnemonic(String text
, Action action
) {
108 int mnemoPos
= text
.indexOf('&');
109 if (mnemoPos
>= 0 && mnemoPos
< text
.length() - 2) {
110 String mnemoChar
= text
.substring(mnemoPos
+ 1, mnemoPos
+ 2).trim();
111 if (mnemoChar
.length() == 1) {
112 action
.putValue(Action
.MNEMONIC_KEY
, Integer
.valueOf((int)mnemoChar
.charAt(0)));
116 text
= text
.replaceAll("&", "");
117 action
.putValue(Action
.NAME
, text
);
120 public static Font
getLabelFont() {
121 return UIManager
.getFont("Label.font");
124 public static Color
getLabelBackground() {
125 return UIManager
.getColor("Label.background");
128 public static Color
getLabelForeground() {
129 return UIManager
.getColor("Label.foreground");
132 public static Icon
getOptionPanelWarningIcon() {
133 return UIManager
.getIcon("OptionPane.warningIcon");
136 public static Icon
getOptionPanelQuestionIcon() {
137 return UIManager
.getIcon("OptionPane.questionIcon");
141 public static String
removeMnemonic(@NotNull String s
) {
142 if (s
.indexOf('&') != -1) {
143 s
= StringUtil
.replace(s
, "&", "");
145 if (s
.indexOf(MNEMONIC
) != -1) {
146 s
= StringUtil
.replace(s
, String
.valueOf(MNEMONIC
), "");
151 public static String
replaceMnemonicAmpersand(final String value
) {
152 if (value
.indexOf('&') >= 0) {
153 boolean useMacMnemonic
= value
.contains("&&");
154 StringBuilder realValue
= new StringBuilder();
156 while (i
< value
.length()) {
157 char c
= value
.charAt(i
);
159 if (i
< value
.length() - 1 && value
.charAt(i
+ 1) == '&') {
160 realValue
.append('&');
168 if (i
< value
.length() - 1 && value
.charAt(i
+ 1) == '&') {
169 if (SystemInfo
.isMac
) {
170 realValue
.append(MNEMONIC
);
175 if (!SystemInfo
.isMac
|| !useMacMnemonic
) {
176 realValue
.append(MNEMONIC
);
186 return realValue
.toString();
191 public static Color
getTableHeaderBackground() {
192 return UIManager
.getColor("TableHeader.background");
195 public static Color
getTreeTextForeground() {
196 return UIManager
.getColor("Tree.textForeground");
199 public static Color
getTreeSelectionBackground() {
200 return UIManager
.getColor("Tree.selectionBackground");
203 public static Color
getTreeTextBackground() {
204 return UIManager
.getColor("Tree.textBackground");
207 public static Color
getListSelectionForeground() {
208 final Color color
= UIManager
.getColor("List.selectionForeground");
210 return UIManager
.getColor("List[Selected].textForeground"); // Nimbus
215 public static Color
getFieldForegroundColor() {
216 return UIManager
.getColor("field.foreground");
219 public static Color
getTableSelectionBackground() {
220 return UIManager
.getColor("Table.selectionBackground");
223 public static Color
getActiveTextColor() {
224 return UIManager
.getColor("textActiveText");
227 public static Color
getInactiveTextColor() {
228 return UIManager
.getColor("textInactiveText");
231 public static Color
getActiveTextFieldBackgroundColor() {
232 return UIManager
.getColor("TextField.background");
235 public static Color
getInactiveTextFieldBackgroundColor() {
236 return UIManager
.getColor("TextField.inactiveBackground");
239 public static Font
getTreeFont() {
240 return UIManager
.getFont("Tree.font");
243 public static Font
getListFont() {
244 return UIManager
.getFont("List.font");
247 public static Color
getTreeSelectionForeground() {
248 return UIManager
.getColor("Tree.selectionForeground");
251 public static Color
getTextInactiveTextColor() {
252 return UIManager
.getColor("textInactiveText");
255 public static void installPopupMenuColorAndFonts(final JComponent contentPane
) {
256 LookAndFeel
.installColorsAndFont(contentPane
, "PopupMenu.background", "PopupMenu.foreground", "PopupMenu.font");
259 public static void installPopupMenuBorder(final JComponent contentPane
) {
260 LookAndFeel
.installBorder(contentPane
, "PopupMenu.border");
263 public static boolean isMotifLookAndFeel() {
264 return "Motif".equals(UIManager
.getLookAndFeel().getID());
267 public static Color
getTreeSelectionBorderColor() {
268 return UIManager
.getColor("Tree.selectionBorderColor");
271 public static Object
getTreeRightChildIndent() {
272 return UIManager
.get("Tree.rightChildIndent");
275 public static Object
getTreeLeftChildIndent() {
276 return UIManager
.get("Tree.leftChildIndent");
279 public static Color
getToolTipBackground() {
280 return UIManager
.getColor("ToolTip.background");
283 public static Color
getToolTipForeground() {
284 return UIManager
.getColor("ToolTip.foreground");
287 public static Color
getComboBoxDisabledForeground() {
288 return UIManager
.getColor("ComboBox.disabledForeground");
291 public static Color
getComboBoxDisabledBackground() {
292 return UIManager
.getColor("ComboBox.disabledBackground");
295 public static Color
getButtonSelectColor() {
296 return UIManager
.getColor("Button.select");
299 public static Integer
getPropertyMaxGutterIconWidth(final String propertyPrefix
) {
300 return (Integer
)UIManager
.get(propertyPrefix
+ ".maxGutterIconWidth");
303 public static Color
getMenuItemDisabledForeground() {
304 return UIManager
.getColor("MenuItem.disabledForeground");
307 public static Object
getMenuItemDisabledForegroundObject() {
308 return UIManager
.get("MenuItem.disabledForeground");
311 public static Object
getTabbedPanePaintContentBorder(final JComponent c
) {
312 return c
.getClientProperty("TabbedPane.paintContentBorder");
315 public static boolean isMenuCrossMenuMnemonics() {
316 return UIManager
.getBoolean("Menu.crossMenuMnemonic");
319 public static Color
getTableBackground() {
320 return UIManager
.getColor("Table.background");
323 public static Color
getTableSelectionForeground() {
324 return UIManager
.getColor("Table.selectionForeground");
327 public static Color
getTableForeground() {
328 return UIManager
.getColor("Table.foreground");
331 public static Color
getListBackground() {
332 return UIManager
.getColor("List.background");
335 public static Color
getListForeground() {
336 return UIManager
.getColor("List.foreground");
339 public static Color
getPanelBackground() {
340 return UIManager
.getColor("Panel.background");
343 public static Color
getTreeForeground() {
344 return UIManager
.getColor("Tree.foreground");
347 public static Color
getTableFocusCellBackground() {
348 return UIManager
.getColor("Table.focusCellBackground");
351 public static Color
getListSelectionBackground() {
352 final Color color
= UIManager
.getColor("List.selectionBackground");
354 return UIManager
.getColor("List[Selected].textBackground"); // Nimbus
359 public static Color
getTextFieldForeground() {
360 return UIManager
.getColor("TextField.foreground");
363 public static Color
getTextFieldBackground() {
364 return UIManager
.getColor("TextField.background");
367 public static Font
getButtonFont() {
368 return UIManager
.getFont("Button.font");
371 public static Font
getToolTipFont() {
372 return UIManager
.getFont("ToolTip.font");
375 public static Color
getTabbedPaneBackground() {
376 return UIManager
.getColor("TabbedPane.background");
379 public static void setSliderIsFilled(final JSlider slider
, final boolean value
) {
380 slider
.putClientProperty("JSlider.isFilled", Boolean
.valueOf(value
));
383 public static Color
getLabelTextForeground() {
384 return UIManager
.getColor("Label.textForeground");
387 public static Color
getControlColor() {
388 return UIManager
.getColor("control");
391 public static Font
getOptionPaneMessageFont() {
392 return UIManager
.getFont("OptionPane.messageFont");
395 public static Color
getSeparatorShadow() {
396 return UIManager
.getColor("Separator.shadow");
399 public static Font
getMenuFont() {
400 return UIManager
.getFont("Menu.font");
403 public static Color
getSeparatorHighlight() {
404 return UIManager
.getColor("Separator.highlight");
407 public static Border
getTableFocusCellHighlightBorder() {
408 return UIManager
.getBorder("Table.focusCellHighlightBorder");
411 public static void setLineStyleAngled(final ClientPropertyHolder component
) {
412 component
.putClientProperty("JTree.lineStyle", "Angled");
415 public static void setLineStyleAngled(final JTree component
) {
416 component
.putClientProperty("JTree.lineStyle", "Angled");
419 public static Color
getTableFocusCellForeground() {
420 return UIManager
.getColor("Table.focusCellForeground");
423 public static Color
getPanelBackgound() {
424 return UIManager
.getColor("Panel.background");
427 public static Border
getTextFieldBorder() {
428 return UIManager
.getBorder("TextField.border");
431 public static Border
getButtonBorder() {
432 return UIManager
.getBorder("Button.border");
435 public static Icon
getErrorIcon() {
436 return UIManager
.getIcon("OptionPane.errorIcon");
439 public static Icon
getInformationIcon() {
440 return UIManager
.getIcon("OptionPane.informationIcon");
443 public static Icon
getQuestionIcon() {
444 return UIManager
.getIcon("OptionPane.questionIcon");
447 public static Icon
getWarningIcon() {
448 return UIManager
.getIcon("OptionPane.warningIcon");
451 public static Icon
getBalloonInformationIcon() {
452 return IconLoader
.getIcon("/general/balloonInformation.png");
455 public static Icon
getBalloonWarningIcon() {
456 return IconLoader
.getIcon("/general/balloonWarning.png");
459 public static Icon
getBalloonErrorIcon() {
460 return IconLoader
.getIcon("/general/balloonError.png");
463 public static Icon
getRadioButtonIcon() {
464 return UIManager
.getIcon("RadioButton.icon");
467 public static Icon
getTreeCollapsedIcon() {
468 return UIManager
.getIcon("Tree.collapsedIcon");
471 public static Icon
getTreeExpandedIcon() {
472 return UIManager
.getIcon("Tree.expandedIcon");
475 public static Border
getTableHeaderCellBorder() {
476 return UIManager
.getBorder("TableHeader.cellBorder");
479 public static Color
getWindowColor() {
480 return UIManager
.getColor("window");
483 public static Color
getTextAreaForeground() {
484 return UIManager
.getColor("TextArea.foreground");
487 public static Color
getOptionPaneBackground() {
488 return UIManager
.getColor("OptionPane.background");
491 @SuppressWarnings({"HardCodedStringLiteral"})
492 public static boolean isUnderQuaquaLookAndFeel() {
493 return UIManager
.getLookAndFeel().getName().contains("Quaqua");
496 @SuppressWarnings({"HardCodedStringLiteral"})
497 public static boolean isUnderNimbusLookAndFeel() {
498 return UIManager
.getLookAndFeel().getName().contains("Nimbus");
501 @SuppressWarnings({"HardCodedStringLiteral"})
502 public static boolean isUnderAquaLookAndFeel() {
503 return UIManager
.getLookAndFeel().getName().contains("Mac OS X");
506 public static boolean isFullRowSelectionLAF() {
507 return isUnderNimbusLookAndFeel() || isUnderQuaquaLookAndFeel();
510 public static boolean isUnderNativeMacLookAndFeel() {
511 return isUnderAquaLookAndFeel() || isUnderQuaquaLookAndFeel();
514 @SuppressWarnings({"HardCodedStringLiteral"})
515 public static void removeQuaquaVisualMarginsIn(Component component
) {
516 if (component
instanceof JComponent
) {
517 final JComponent jComponent
= (JComponent
)component
;
518 final Component
[] children
= jComponent
.getComponents();
519 for (Component child
: children
) {
520 removeQuaquaVisualMarginsIn(child
);
523 jComponent
.putClientProperty("Quaqua.Component.visualMargin", new Insets(0, 0, 0, 0));
527 public static boolean isControlKeyDown(MouseEvent mouseEvent
) {
528 return SystemInfo
.isMac ? mouseEvent
.isMetaDown() : mouseEvent
.isControlDown();
531 public static String
[] getValidFontNames(final boolean familyName
) {
532 Set
<String
> result
= new TreeSet
<String
>();
533 Font
[] fonts
= GraphicsEnvironment
.getLocalGraphicsEnvironment().getAllFonts();
534 for (Font font
: fonts
) {
535 // Adds fonts that can display symbols at [A, Z] + [a, z] + [0, 9]
537 if (font
.canDisplay('a') && font
.canDisplay('z') && font
.canDisplay('A') && font
.canDisplay('Z') && font
.canDisplay('0') &&
538 font
.canDisplay('1')) {
539 result
.add(familyName ? font
.getFamily() : font
.getName());
542 catch (Exception e
) {
543 // JRE has problems working with the font. Just skip.
546 return ArrayUtil
.toStringArray(result
);
549 public static String
[] getStandardFontSizes() {
550 return new String
[]{"8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48", "72"};
553 public static void setupEnclosingDialogBounds(final JComponent component
) {
554 component
.revalidate();
556 final Window window
= SwingUtilities
.windowForComponent(component
);
557 if (window
!= null &&
558 (window
.getSize().height
< window
.getMinimumSize().height
|| window
.getSize().width
< window
.getMinimumSize().width
)) {
563 public static String
displayPropertiesToCSS(Font font
, Color fg
) {
564 @NonNls StringBuilder rule
= new StringBuilder("body {");
566 rule
.append(" font-family: ");
567 rule
.append(font
.getFamily());
569 rule
.append(" font-size: ");
570 rule
.append(font
.getSize());
573 rule
.append(" font-weight: 700 ; ");
575 if (font
.isItalic()) {
576 rule
.append(" font-style: italic ; ");
580 rule
.append(" color: #");
581 if (fg
.getRed() < 16) {
584 rule
.append(Integer
.toHexString(fg
.getRed()));
585 if (fg
.getGreen() < 16) {
588 rule
.append(Integer
.toHexString(fg
.getGreen()));
589 if (fg
.getBlue() < 16) {
592 rule
.append(Integer
.toHexString(fg
.getBlue()));
596 return rule
.toString();
601 * @param x top left X coordinate.
602 * @param y top left Y coordinate.
603 * @param x1 right bottom X coordinate.
604 * @param y1 right bottom Y coordinate.
606 public static void drawDottedRectangle(Graphics g
, int x
, int y
, int x1
, int y1
) {
608 for (i1
= x
; i1
<= x1
; i1
+= 2) {
609 drawLine(g
, i1
, y
, i1
, y
);
612 for (i1
= i1
!= x1
+ 1 ? y
+ 2 : y
+ 1; i1
<= y1
; i1
+= 2) {
613 drawLine(g
, x1
, i1
, x1
, i1
);
616 for (i1
= i1
!= y1
+ 1 ? x1
- 2 : x1
- 1; i1
>= x
; i1
-= 2) {
617 drawLine(g
, i1
, y1
, i1
, y1
);
620 for (i1
= i1
!= x
- 1 ? y1
- 2 : y1
- 1; i1
>= y
; i1
-= 2) {
621 drawLine(g
, x
, i1
, x
, i1
);
625 public static void applyRenderingHints(final Graphics g
) {
626 Toolkit tk
= Toolkit
.getDefaultToolkit();
627 //noinspection HardCodedStringLiteral
628 Map map
= (Map
)tk
.getDesktopProperty("awt.font.desktophints");
630 ((Graphics2D
)g
).addRenderingHints(map
);
635 public static void dispatchAllInvocationEvents() {
636 assert SwingUtilities
.isEventDispatchThread() : Thread
.currentThread();
637 final EventQueue eventQueue
= Toolkit
.getDefaultToolkit().getSystemEventQueue();
639 AWTEvent event
= eventQueue
.peekEvent();
640 if (event
== null) break;
642 AWTEvent event1
= eventQueue
.getNextEvent();
643 if (event1
instanceof InvocationEvent
) {
644 ((InvocationEvent
)event1
).dispatch();
647 catch (Exception e
) {
654 public static void pump() {
655 assert !SwingUtilities
.isEventDispatchThread();
656 final BlockingQueue
<Object
> queue
= new LinkedBlockingQueue
<Object
>();
657 SwingUtilities
.invokeLater(new Runnable() {
665 catch (InterruptedException e
) {
670 public static void addAwtListener(final AWTEventListener listener
, long mask
, Disposable parent
) {
671 Toolkit
.getDefaultToolkit().addAWTEventListener(listener
, mask
);
672 Disposer
.register(parent
, new Disposable() {
673 public void dispose() {
674 Toolkit
.getDefaultToolkit().removeAWTEventListener(listener
);
679 public static void drawVDottedLine(Graphics2D g
, int lineX
, int startY
, int endY
, final Color bgColor
, final Color fgColor
) {
681 drawLine(g
, lineX
, startY
, lineX
, endY
);
685 for (int i
= (startY
/ 2) * 2; i
< endY
; i
+= 2) {
686 g
.drawRect(lineX
, i
, 0, 0);
690 public static void drawHDottedLine(Graphics2D g
, int startX
, int endX
, int lineY
, final Color bgColor
, final Color fgColor
) {
692 drawLine(g
, startX
, lineY
, endX
, lineY
);
696 for (int i
= (startX
/ 2) * 2; i
< endX
; i
+= 2) {
697 g
.drawRect(i
, lineY
, 0, 0);
701 public static void drawDottedLine(Graphics2D g
, int x1
, int y1
, int x2
, int y2
, final Color bgColor
, final Color fgColor
) {
703 drawVDottedLine(g
, x1
, y1
, y2
, bgColor
, fgColor
);
706 drawHDottedLine(g
, x1
, x2
, y1
, bgColor
, fgColor
);
709 throw new IllegalArgumentException("Only vertical or horizontal lines are supported");
713 public static boolean isFocusAncestor(@NotNull final JComponent component
) {
714 final Component owner
= KeyboardFocusManager
.getCurrentKeyboardFocusManager().getFocusOwner();
715 if (owner
== null) return false;
716 if (owner
== component
) return true;
717 return SwingUtilities
.isDescendingFrom(owner
, component
);
721 public static boolean isCloseClick(MouseEvent e
) {
722 return isCloseClick(e
, MouseEvent
.MOUSE_PRESSED
);
725 public static boolean isCloseClick(MouseEvent e
, int effectiveType
) {
726 if (e
.isPopupTrigger() || e
.getID() != effectiveType
) return false;
727 return e
.getButton() == MouseEvent
.BUTTON2
|| e
.getButton() == MouseEvent
.BUTTON1
&& e
.isShiftDown();
730 public static boolean isActionClick(MouseEvent e
) {
731 return isActionClick(e
, MouseEvent
.MOUSE_PRESSED
);
734 public static boolean isActionClick(MouseEvent e
, int effectiveType
) {
735 if (isCloseClick(e
) || e
.isPopupTrigger() || e
.getID() != effectiveType
) return false;
736 return e
.getButton() == MouseEvent
.BUTTON1
;
741 Color
getBgFillColor(@NotNull JComponent c
) {
742 final Component parent
= findNearestOpaque(c
);
743 return parent
== null ? c
.getBackground() : parent
.getBackground();
748 Component
findNearestOpaque(JComponent c
) {
749 Component eachParent
= c
;
750 while (eachParent
!= null) {
751 if (eachParent
.isOpaque()) return eachParent
;
752 eachParent
= eachParent
.getParent();
759 public static String
getCssFontDeclaration(final Font font
) {
760 return "<style> body, div, td { font-family: " + font
.getFamily() + "; font-size: " + font
.getSize() + "; } </style>";
763 public static boolean isWinLafOnVista() {
764 return (SystemInfo
.isWindowsVista
|| SystemInfo
.isWindows7
) && "Windows".equals(UIManager
.getLookAndFeel().getName());
767 public static boolean isStandardMenuLAF() {
768 return isWinLafOnVista() || "Nimbus".equals(UIManager
.getLookAndFeel().getName());
771 public static Color
getFocusedFillColor() {
772 return toAlpha(getListSelectionBackground(), 100);
775 public static Color
getFocusedBoundsColor() {
776 return getBoundsColor();
779 public static Color
getBoundsColor() {
780 return new Color(128, 128, 128);
783 public static Color
getBoundsColor(boolean focused
) {
784 return focused ?
getFocusedBoundsColor() : getBoundsColor();
787 public static Color
toAlpha(final Color color
, final int alpha
) {
788 Color actual
= color
!= null ? color
: Color
.black
;
789 return new Color(actual
.getRed(), actual
.getGreen(), actual
.getBlue(), alpha
);
792 public static void requestFocus(@NotNull final JComponent c
) {
797 SwingUtilities
.invokeLater(new Runnable() {
805 //todo maybe should do for all kind of listeners via the AWTEventMulticaster class
806 public static void dispose(final Component c
) {
807 if (c
== null) return;
809 final MouseListener
[] mouseListeners
= c
.getMouseListeners();
810 for (MouseListener each
: mouseListeners
) {
811 c
.removeMouseListener(each
);
814 final MouseMotionListener
[] motionListeners
= c
.getMouseMotionListeners();
815 for (MouseMotionListener each
: motionListeners
) {
816 c
.removeMouseMotionListener(each
);
819 final MouseWheelListener
[] mouseWheelListeners
= c
.getMouseWheelListeners();
820 for (MouseWheelListener each
: mouseWheelListeners
) {
821 c
.removeMouseWheelListener(each
);
825 public static void disposeProgress(final JProgressBar progress
) {
826 if (!isUnderNativeMacLookAndFeel()) return;
828 SwingUtilities
.invokeLater(new Runnable() {
830 if (isToDispose(progress
)) {
831 progress
.getUI().uninstallUI(progress
);
832 progress
.putClientProperty("isDisposed", Boolean
.TRUE
);
838 private static boolean isToDispose(final JProgressBar progress
) {
839 final ProgressBarUI ui
= progress
.getUI();
841 if (ui
== null) return false;
842 if (Boolean
.TYPE
.equals(progress
.getClientProperty("isDisposed"))) return false;
845 final Field progressBarField
= ReflectionUtil
.findField(ui
.getClass(), JProgressBar
.class, "progressBar");
846 progressBarField
.setAccessible(true);
847 return progressBarField
.get(ui
) != null;
849 catch (NoSuchFieldException e
) {
852 catch (IllegalAccessException e
) {
858 public static Component
findUltimateParent(Component c
) {
859 if (c
== null) return null;
861 Component eachParent
= c
;
863 if (eachParent
.getParent() == null) return eachParent
;
864 eachParent
= eachParent
.getParent();
868 public static void setToolkitModal(final JDialog dialog
) {
870 final Class
<?
> modalityType
= dialog
.getClass().getClassLoader().loadClass("java.awt.Dialog$ModalityType");
871 final Field field
= modalityType
.getField("TOOLKIT_MODAL");
872 final Object value
= field
.get(null);
874 final Method method
= dialog
.getClass().getMethod("setModalityType", modalityType
);
875 method
.invoke(dialog
, value
);
877 catch (Exception e
) {
882 public static void updateDialogIcon(final JDialog dialog
, final List
<Image
> images
) {
884 final Method method
= dialog
.getClass().getMethod("setIconImages", List
.class);
885 method
.invoke(dialog
, images
);
887 catch (Exception e
) {
892 public static boolean hasJdk6Dialogs() {
894 UIUtil
.class.getClassLoader().loadClass("java.awt.Dialog$ModalityType");
896 catch (Throwable e
) {
902 public static Color
getBorderActiveColor() {
906 public static Color
getBorderInactiveColor() {
907 return INACTIVE_COLOR
;
910 public static Color
getBorderSeparatorColor() {
911 return SEPARATOR_COLOR
;
914 public static HTMLEditorKit
getHTMLEditorKit() {
915 final HTMLEditorKit kit
= new HTMLEditorKit();
917 Font font
= UIManager
.getFont("Label.font");
918 @NonNls String family
= font
!= null ? font
.getFamily() : "Tahoma";
919 int size
= font
!= null ? font
.getSize() : 11;
921 final StyleSheet styleSheet
= kit
.getStyleSheet();
922 styleSheet
.addRule(String
.format("body, div, p { font-family: %s; font-size: %s; } p { margin-top: 0; }", family
, size
));
923 kit
.setStyleSheet(styleSheet
);
928 public static void removeScrollBorder(final Component c
) {
930 public boolean visit(final Component component
) {
931 if (component
instanceof JScrollPane
) {
932 if (!hasNonPrimitiveParents(c
, component
)) {
933 final JScrollPane scrollPane
= (JScrollPane
)component
;
934 Integer keepBorderSides
= (Integer
) scrollPane
.getClientProperty(KEEP_BORDER_SIDES
);
935 if (keepBorderSides
!= null) {
936 if (scrollPane
.getBorder() instanceof LineBorder
) {
937 Color color
= ((LineBorder
) scrollPane
.getBorder()).getLineColor();
938 scrollPane
.setBorder(new SideBorder(color
, keepBorderSides
.intValue()));
941 scrollPane
.setBorder(new SideBorder(getBoundsColor(), keepBorderSides
.intValue()));
945 scrollPane
.setBorder(null);
954 public static boolean hasNonPrimitiveParents(Component stopParent
, Component c
) {
955 Component eachParent
= c
.getParent();
957 if (eachParent
== null || eachParent
== stopParent
) return false;
958 if (!isPrimitive(eachParent
)) return true;
959 eachParent
= eachParent
.getParent();
963 public static boolean isPrimitive(Component c
) {
964 return c
instanceof JPanel
|| c
instanceof JLayeredPane
;
967 public static Point
getCenterPoint(Dimension container
, Dimension child
) {
968 return getCenterPoint(new Rectangle(new Point(), container
), child
);
971 public static Point
getCenterPoint(Rectangle container
, Dimension child
) {
972 Point result
= new Point();
974 Point containerLocation
= container
.getLocation();
975 Dimension containerSize
= container
.getSize();
977 result
.x
= containerLocation
.x
+ (containerSize
.width
/ 2 - child
.width
/ 2);
978 result
.y
= containerLocation
.y
+ (containerSize
.height
/ 2 - child
.height
/ 2);
983 public static String
toHtml(String html
) {
984 return toHtml(html
, 0);
988 public static String
toHtml(String html
, final int hPadding
) {
989 html
= CLOSE_TAG_PATTERN
.matcher(html
).replaceAll("<$1$2></$1>");
990 Font font
= UIManager
.getFont("Label.font");
991 @NonNls String family
= font
!= null ? font
.getFamily() : "Tahoma";
992 int size
= font
!= null ? font
.getSize() : 11;
993 return "<html><style>body { font-family: "
994 + family
+ "; font-size: "
995 + size
+ ";} ul li {list-style-type:circle;}</style>"
996 + addPadding(html
, hPadding
) + "</html>";
999 public static String
addPadding(final String html
, int hPadding
) {
1000 return String
.format("<p style=\"margin: 0 %dpx 0 %dpx;\">%s</p>", hPadding
, hPadding
, html
);
1003 public static void invokeLaterIfNeeded(@NotNull Runnable runnable
) {
1004 if (SwingUtilities
.isEventDispatchThread()) {
1007 SwingUtilities
.invokeLater(runnable
);
1012 * Invoke and wait in the event dispatch thread
1013 * or in the current thread if the current thread
1014 * is event queue thread.
1016 * @param runnable a runnable to invoke
1018 public static void invokeAndWaitIfNeeded(@NotNull Runnable runnable
) {
1019 if (SwingUtilities
.isEventDispatchThread()) {
1023 SwingUtilities
.invokeAndWait(runnable
);
1025 catch (Exception e
) {
1031 public static boolean isFocusProxy(@Nullable Component c
) {
1032 return c
instanceof JComponent
&& Boolean
.TRUE
.equals(((JComponent
)c
).getClientProperty(FOCUS_PROXY_KEY
));
1035 public static void setFocusProxy(JComponent c
, boolean isProxy
) {
1036 c
.putClientProperty(FOCUS_PROXY_KEY
, isProxy ? Boolean
.TRUE
: null);
1039 public static class LeglessTreeUi
extends BasicTreeUI
{
1041 protected void paintHorizontalPartOfLeg(final Graphics g
,
1042 final Rectangle clipBounds
,
1043 final Insets insets
,
1044 final Rectangle bounds
,
1045 final TreePath path
,
1047 final boolean isExpanded
,
1048 final boolean hasBeenExpanded
,
1049 final boolean isLeaf
) {
1054 protected boolean isToggleSelectionEvent(MouseEvent e
) {
1055 return SwingUtilities
.isLeftMouseButton(e
) && (SystemInfo
.isMac ? e
.isMetaDown() : e
.isControlDown()) && !e
.isPopupTrigger();
1059 protected void paintVerticalPartOfLeg(final Graphics g
, final Rectangle clipBounds
, final Insets insets
, final TreePath path
) {
1063 public static boolean isPrinting(Graphics g
) {
1064 return g
instanceof PrintGraphics
;