When checking for canPaint() && isDispatchThread there should be check if we're print...
[fedora-idea.git] / platform / util / src / com / intellij / util / ui / UIUtil.java
bloba70d4b8ab392df24c6a693b7ded64e3df9a041c3
1 /*
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;
33 import javax.swing.*;
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;
41 import java.awt.*;
42 import java.awt.event.*;
43 import java.lang.reflect.Field;
44 import java.lang.reflect.Method;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Set;
48 import java.util.TreeSet;
49 import java.util.concurrent.BlockingQueue;
50 import java.util.concurrent.LinkedBlockingQueue;
51 import java.util.regex.Pattern;
53 /**
54 * @author max
56 public class UIUtil {
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");
74 private UIUtil() {
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");
140 @NotNull
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), "");
148 return s;
151 public static String replaceMnemonicAmpersand(final String value) {
152 if (value.indexOf('&') >= 0) {
153 boolean useMacMnemonic = value.contains("&&");
154 StringBuilder realValue = new StringBuilder();
155 int i = 0;
156 while (i < value.length()) {
157 char c = value.charAt(i);
158 if (c == '\\') {
159 if (i < value.length() - 1 && value.charAt(i + 1) == '&') {
160 realValue.append('&');
161 i++;
163 else {
164 realValue.append(c);
167 else if (c == '&') {
168 if (i < value.length() - 1 && value.charAt(i + 1) == '&') {
169 if (SystemInfo.isMac) {
170 realValue.append(MNEMONIC);
172 i++;
174 else {
175 if (!SystemInfo.isMac || !useMacMnemonic) {
176 realValue.append(MNEMONIC);
180 else {
181 realValue.append(c);
183 i++;
186 return realValue.toString();
188 return value;
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");
209 if (color == null) {
210 return UIManager.getColor("List[Selected].textForeground"); // Nimbus
212 return color;
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");
353 if (color == null) {
354 return UIManager.getColor("List[Selected].textBackground"); // Nimbus
356 return color;
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]
536 try {
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();
555 component.repaint();
556 final Window window = SwingUtilities.windowForComponent(component);
557 if (window != null &&
558 (window.getSize().height < window.getMinimumSize().height || window.getSize().width < window.getMinimumSize().width)) {
559 window.pack();
563 public static String displayPropertiesToCSS(Font font, Color fg) {
564 @NonNls StringBuilder rule = new StringBuilder("body {");
565 if (font != null) {
566 rule.append(" font-family: ");
567 rule.append(font.getFamily());
568 rule.append(" ; ");
569 rule.append(" font-size: ");
570 rule.append(font.getSize());
571 rule.append("pt ;");
572 if (font.isBold()) {
573 rule.append(" font-weight: 700 ; ");
575 if (font.isItalic()) {
576 rule.append(" font-style: italic ; ");
579 if (fg != null) {
580 rule.append(" color: #");
581 if (fg.getRed() < 16) {
582 rule.append('0');
584 rule.append(Integer.toHexString(fg.getRed()));
585 if (fg.getGreen() < 16) {
586 rule.append('0');
588 rule.append(Integer.toHexString(fg.getGreen()));
589 if (fg.getBlue() < 16) {
590 rule.append('0');
592 rule.append(Integer.toHexString(fg.getBlue()));
593 rule.append(" ; ");
595 rule.append(" }");
596 return rule.toString();
600 * @param g
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) {
607 int i1;
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");
629 if (map != null) {
630 ((Graphics2D)g).addRenderingHints(map);
634 @TestOnly
635 public static void dispatchAllInvocationEvents() {
636 assert SwingUtilities.isEventDispatchThread() : Thread.currentThread();
637 final EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
638 while (true) {
639 AWTEvent event = eventQueue.peekEvent();
640 if (event == null) break;
641 try {
642 AWTEvent event1 = eventQueue.getNextEvent();
643 if (event1 instanceof InvocationEvent) {
644 ((InvocationEvent)event1).dispatch();
647 catch (Exception e) {
648 LOG.error(e); //?
653 @TestOnly
654 public static void pump() {
655 assert !SwingUtilities.isEventDispatchThread();
656 final BlockingQueue<Object> queue = new LinkedBlockingQueue<Object>();
657 SwingUtilities.invokeLater(new Runnable() {
658 public void run() {
659 queue.offer(queue);
662 try {
663 queue.take();
665 catch (InterruptedException e) {
666 LOG.error(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) {
680 g.setColor(bgColor);
681 drawLine(g, lineX, startY, lineX, endY);
683 g.setColor(fgColor);
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) {
691 g.setColor(bgColor);
692 drawLine(g, startX, lineY, endX, lineY);
694 g.setColor(fgColor);
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) {
702 if (x1 == x2) {
703 drawVDottedLine(g, x1, y1, y2, bgColor, fgColor);
705 else if (y1 == y2) {
706 drawHDottedLine(g, x1, x2, y1, bgColor, fgColor);
708 else {
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;
739 @NotNull
740 public static
741 Color getBgFillColor(@NotNull JComponent c) {
742 final Component parent = findNearestOpaque(c);
743 return parent == null ? c.getBackground() : parent.getBackground();
746 @Nullable
747 public static
748 Component findNearestOpaque(JComponent c) {
749 Component eachParent = c;
750 while (eachParent != null) {
751 if (eachParent.isOpaque()) return eachParent;
752 eachParent = eachParent.getParent();
755 return eachParent;
758 @NonNls
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) {
793 if (c.isShowing()) {
794 c.requestFocus();
796 else {
797 SwingUtilities.invokeLater(new Runnable() {
798 public void run() {
799 c.requestFocus();
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() {
829 public void run() {
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;
844 try {
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) {
850 return true;
852 catch (IllegalAccessException e) {
853 return true;
857 @Nullable
858 public static Component findUltimateParent(Component c) {
859 if (c == null) return null;
861 Component eachParent = c;
862 while (true) {
863 if (eachParent.getParent() == null) return eachParent;
864 eachParent = eachParent.getParent();
868 public static void setToolkitModal(final JDialog dialog) {
869 try {
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) {
878 // ignore - no JDK 6
882 public static void updateDialogIcon(final JDialog dialog, final List<Image> images) {
883 try {
884 final Method method = dialog.getClass().getMethod("setIconImages", List.class);
885 method.invoke(dialog, images);
887 catch (Exception e) {
888 // ignore - no JDK 6
892 public static boolean hasJdk6Dialogs() {
893 try {
894 UIUtil.class.getClassLoader().loadClass("java.awt.Dialog$ModalityType");
896 catch (Throwable e) {
897 return false;
899 return true;
902 public static Color getBorderActiveColor() {
903 return ACTIVE_COLOR;
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);
925 return kit;
928 public static void removeScrollBorder(final Component c) {
929 new AwtVisitor(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()));
940 else {
941 scrollPane.setBorder(new SideBorder(getBoundsColor(), keepBorderSides.intValue()));
944 else {
945 scrollPane.setBorder(null);
949 return false;
954 public static boolean hasNonPrimitiveParents(Component stopParent, Component c) {
955 Component eachParent = c.getParent();
956 while (true) {
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);
980 return result;
983 public static String toHtml(String html) {
984 return toHtml(html, 0);
987 @NonNls
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()) {
1005 runnable.run();
1006 } else {
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()) {
1020 runnable.run();
1021 } else {
1022 try {
1023 SwingUtilities.invokeAndWait(runnable);
1025 catch (Exception e) {
1026 LOG.error(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 {
1040 @Override
1041 protected void paintHorizontalPartOfLeg(final Graphics g,
1042 final Rectangle clipBounds,
1043 final Insets insets,
1044 final Rectangle bounds,
1045 final TreePath path,
1046 final int row,
1047 final boolean isExpanded,
1048 final boolean hasBeenExpanded,
1049 final boolean isLeaf) {
1053 @Override
1054 protected boolean isToggleSelectionEvent(MouseEvent e) {
1055 return SwingUtilities.isLeftMouseButton(e) && (SystemInfo.isMac ? e.isMetaDown() : e.isControlDown()) && !e.isPopupTrigger();
1058 @Override
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;