/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package org.gephi.ui.utils;
// Copied from org.netbeans.lib.profiler.ui
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.lang.reflect.InvocationTargetException;
import javax.swing.AbstractButton;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.table.JTableHeader;
//Copied from org.netbeans.lib.profiler.ui
public final class UIUtils {
public static final float ALTERNATE_ROW_DARKER_FACTOR = 0.96f;
private static Color unfocusedSelBg;
private static Color unfocusedSelFg;
//~ Methods ------------------------------------------------------------------------------------------------------------------
/** Determines if current L&F is AquaLookAndFeel */
public static boolean isAquaLookAndFeel() {
// is current L&F some kind of AquaLookAndFeel?
return UIManager.getLookAndFeel().getID().equals("Aqua"); //NOI18N
}
public static Color getDarker(Color c) {
if (c.equals(Color.WHITE)) {
return new Color(244, 244, 244);
}
return getSafeColor((int) (c.getRed() * ALTERNATE_ROW_DARKER_FACTOR), (int) (c.getGreen() * ALTERNATE_ROW_DARKER_FACTOR),
(int) (c.getBlue() * ALTERNATE_ROW_DARKER_FACTOR));
}
public static Color getForegroundColorForBackground(Color background) {
return (background.getRed() < 100 || background.getGreen() < 100 || background.getRed() < 100) ? Color.white : Color.black;
}
public static Color getDarkerLine(Color c, float alternateRowDarkerFactor) {
return getSafeColor((int) (c.getRed() * alternateRowDarkerFactor), (int) (c.getGreen() * alternateRowDarkerFactor),
(int) (c.getBlue() * alternateRowDarkerFactor));
}
public static int getDefaultRowHeight() {
return new JLabel("X").getPreferredSize().height + 2; //NOI18N
}
/** Determines if current L&F is GTKLookAndFeel */
public static boolean isGTKLookAndFeel() {
// is current L&F some kind of GTKLookAndFeel?
return UIManager.getLookAndFeel().getID().equals("GTK"); //NOI18N
}
/** Determines if current L&F is Nimbus */
public static boolean isNimbusLookAndFeel() {
// is current L&F Nimbus?
return UIManager.getLookAndFeel().getID().equals("Nimbus"); //NOI18N
}
/** Determines if current L&F is GTK using Nimbus theme */
public static boolean isNimbusGTKTheme() {
// is current L&F GTK using Nimbus theme?
return isGTKLookAndFeel() && "nimbus".equals(Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Net/ThemeName")); //NOI18N
}
/** Determines if current L&F is Nimbus or GTK with Nimbus theme*/
public static boolean isNimbus() {
// is current L&F Nimbus or GTK with Nimbus theme?
return isNimbusLookAndFeel() || isNimbusGTKTheme();
}
/** Determines if current L&F is MetalLookAndFeel */
public static boolean isMetalLookAndFeel() {
// is current L&F some kind of MetalLookAndFeel?
return UIManager.getLookAndFeel().getID().equals("Metal"); //NOI18N
}
// Returns next enabled tab of JTabbedPane
public static int getNextSubTabIndex(JTabbedPane tabs, int tabIndex) {
int nextTabIndex = tabIndex;
for (int i = 0; i < tabs.getComponentCount(); i++) {
nextTabIndex++;
if (nextTabIndex == tabs.getComponentCount()) {
nextTabIndex = 0;
}
if (tabs.isEnabledAt(nextTabIndex)) {
break;
}
}
return nextTabIndex;
}
public static Window getParentWindow(Component comp) {
while ((comp != null) && !(comp instanceof Window)) {
comp = comp.getParent();
}
return (Window) comp;
}
// Returns previous enabled tab of JTabbedPane
public static int getPreviousSubTabIndex(JTabbedPane tabs, int tabIndex) {
int previousTabIndex = tabIndex;
for (int i = 0; i < tabs.getComponentCount(); i++) {
previousTabIndex--;
if (previousTabIndex < 0) {
previousTabIndex = tabs.getComponentCount() - 1;
}
if (tabs.isEnabledAt(previousTabIndex)) {
break;
}
}
return previousTabIndex;
}
public static Color getSafeColor(int red, int green, int blue) {
red = Math.max(red, 0);
red = Math.min(red, 255);
green = Math.max(green, 0);
green = Math.min(green, 255);
blue = Math.max(blue, 0);
blue = Math.min(blue, 255);
return new Color(red, green, blue);
}
// Copied from org.openide.awt.HtmlLabelUI
/** Get the system-wide unfocused selection background color */
public static Color getUnfocusedSelectionBackground() {
if (unfocusedSelBg == null) {
//allow theme/ui custom definition
unfocusedSelBg = UIManager.getColor("nb.explorer.unfocusedSelBg"); //NOI18N
if (unfocusedSelBg == null) {
//try to get standard shadow color
unfocusedSelBg = UIManager.getColor("controlShadow"); //NOI18N
if (unfocusedSelBg == null) {
//Okay, the look and feel doesn't suport it, punt
unfocusedSelBg = Color.lightGray;
}
//Lighten it a bit because disabled text will use controlShadow/
//gray
if (!Color.WHITE.equals(unfocusedSelBg.brighter())) {
unfocusedSelBg = unfocusedSelBg.brighter();
}
}
}
return unfocusedSelBg;
}
// Copied from org.openide.awt.HtmlLabelUI
/** Get the system-wide unfocused selection foreground color */
public static Color getUnfocusedSelectionForeground() {
if (unfocusedSelFg == null) {
//allow theme/ui custom definition
unfocusedSelFg = UIManager.getColor("nb.explorer.unfocusedSelFg"); //NOI18N
if (unfocusedSelFg == null) {
//try to get standard shadow color
unfocusedSelFg = UIManager.getColor("textText"); //NOI18N
if (unfocusedSelFg == null) {
//Okay, the look and feel doesn't suport it, punt
unfocusedSelFg = Color.BLACK;
}
}
}
return unfocusedSelFg;
}
private static Color profilerResultsBackground;
private static Color getGTKProfilerResultsBackground() {
int[] pixels = new int[1];
pixels[0] = -1;
// Prepare textarea to grab the color from
JTextArea textArea = new JTextArea();
textArea.setSize(new Dimension(10, 10));
textArea.doLayout();
// Print the textarea to an image
Image image = new BufferedImage(textArea.getSize().width, textArea.getSize().height, BufferedImage.TYPE_INT_RGB);
textArea.printAll(image.getGraphics());
// Grab appropriate pixels to get the color
PixelGrabber pixelGrabber = new PixelGrabber(image, 5, 5, 1, 1, pixels, 0, 1);
try {
pixelGrabber.grabPixels();
if (pixels[0] == -1) {
return Color.WHITE; // System background not customized
}
} catch (InterruptedException e) {
return getNonGTKProfilerResultsBackground();
}
return pixels[0] != -1 ? new Color(pixels[0]) : getNonGTKProfilerResultsBackground();
}
private static Color getNonGTKProfilerResultsBackground() {
return UIManager.getColor("Table.background"); // NOI18N
}
public static Color getProfilerResultsBackground() {
if (profilerResultsBackground == null) {
if (isGTKLookAndFeel() || isNimbusLookAndFeel()) {
profilerResultsBackground = getGTKProfilerResultsBackground();
} else {
profilerResultsBackground = getNonGTKProfilerResultsBackground();
}
if (profilerResultsBackground == null) {
profilerResultsBackground = Color.WHITE;
}
}
return profilerResultsBackground;
}
/** Determines if current L&F is Windows Classic LookAndFeel */
public static boolean isWindowsClassicLookAndFeel() {
if (!isWindowsLookAndFeel()) {
return false;
}
return (!isWindowsXPLookAndFeel() && !isWindowsVistaLookAndFeel());
}
/** Determines if current L&F is WindowsLookAndFeel */
public static boolean isWindowsLookAndFeel() {
// is current L&F some kind of WindowsLookAndFeel?
return UIManager.getLookAndFeel().getID().equals("Windows"); //NOI18N
}
/** Determines if current L&F is Windows XP LookAndFeel */
public static boolean isWindowsXPLookAndFeel() {
if (!isWindowsLookAndFeel()) {
return false;
}
// is XP theme active in the underlying OS?
boolean xpThemeActiveOS = Boolean.TRUE.equals(Toolkit.getDefaultToolkit().getDesktopProperty("win.xpstyle.themeActive")); //NOI18N
// is XP theme disabled by the application?
boolean xpThemeDisabled = (System.getProperty("swing.noxp") != null); // NOI18N
boolean vistaOs = System.getProperty("os.version").startsWith("6.0");
return ((xpThemeActiveOS) && (!xpThemeDisabled) && !vistaOs);
}
public static boolean isWindowsVistaLookAndFeel() {
if (!isWindowsLookAndFeel()) {
return false;
}
// is XP theme active in the underlying OS?
boolean xpThemeActiveOS = Boolean.TRUE.equals(Toolkit.getDefaultToolkit().getDesktopProperty("win.xpstyle.themeActive")); //NOI18N
// is XP theme disabled by the application?
boolean xpThemeDisabled = (System.getProperty("swing.noxp") != null); // NOI18N
boolean vistaOs = System.getProperty("os.version").startsWith("6.0");
return ((xpThemeActiveOS) && (!xpThemeDisabled) && vistaOs);
}
// Classic Windows LaF doesn't draw dotted focus rectangle inside JButton if parent is JToolBar,
// XP Windows LaF doesn't draw dotted focus rectangle inside JButton at all
// This method installs customized Windows LaF that draws dotted focus rectangle inside JButton always
// On JDK 1.5 the XP Windows LaF enforces special border to all buttons, overriding any custom border
// set by setBorder(). Class responsible for this is WindowsButtonListener. See Issue 71546.
// Also fixes buttons size in JToolbar.
/** Ensures that focus will be really painted if button is focused
* and fixes using custom border for JDK 1.5 & XP LaF
*/
public static void fixButtonUI(AbstractButton button) {
// JButton
if (button.getUI() instanceof com.sun.java.swing.plaf.windows.WindowsButtonUI) {
button.setUI(new com.sun.java.swing.plaf.windows.WindowsButtonUI() {
protected BasicButtonListener createButtonListener(AbstractButton b) {
return new BasicButtonListener(b); // Fix for Issue 71546
}
protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect,
Rectangle iconRect) {
int width = b.getWidth();
int height = b.getHeight();
g.setColor(getFocusColor());
javax.swing.plaf.basic.BasicGraphicsUtils.drawDashedRect(g, dashedRectGapX, dashedRectGapY,
width - dashedRectGapWidth,
height - dashedRectGapHeight);
}
});
} // JToggleButton
else if (button.getUI() instanceof com.sun.java.swing.plaf.windows.WindowsToggleButtonUI) {
button.setUI(new com.sun.java.swing.plaf.windows.WindowsToggleButtonUI() {
protected BasicButtonListener createButtonListener(AbstractButton b) {
return new BasicButtonListener(b); // Fix for Issue 71546
}
protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect,
Rectangle iconRect) {
int width = b.getWidth();
int height = b.getHeight();
g.setColor(getFocusColor());
javax.swing.plaf.basic.BasicGraphicsUtils.drawDashedRect(g, dashedRectGapX, dashedRectGapY,
width - dashedRectGapWidth,
height - dashedRectGapHeight);
}
});
}
}
private static BufferedImage createTableScreenshot(Component component) {
Component source;
Dimension sourceSize;
JTable table;
if (component instanceof JTable) {
table = (JTable) component;
if ((table.getTableHeader() == null) || !table.getTableHeader().isVisible()) {
return createGeneralComponentScreenshot(component);
}
source = table;
sourceSize = table.getSize();
} else if (component instanceof JViewport && ((JViewport) component).getView() instanceof JTable) {
JViewport viewport = (JViewport) component;
table = (JTable) viewport.getView();
if ((table.getTableHeader() == null) || !table.getTableHeader().isVisible()) {
return createGeneralComponentScreenshot(component);
}
if (table.getSize().height > viewport.getSize().height) {
source = viewport;
sourceSize = viewport.getSize();
} else {
source = table;
sourceSize = table.getSize();
}
} else {
throw new IllegalArgumentException("Component can only be JTable or JViewport holding JTable"); // NOI18N
}
final JTableHeader tableHeader = table.getTableHeader();
Dimension tableHeaderSize = tableHeader.getSize();
BufferedImage tableScreenshot = new BufferedImage(sourceSize.width, tableHeaderSize.height + sourceSize.height,
BufferedImage.TYPE_INT_RGB);
final Graphics tableScreenshotGraphics = tableScreenshot.getGraphics();
// Component.printAll has to run in AWT Thread to print component contents correctly
if (SwingUtilities.isEventDispatchThread()) {
tableHeader.printAll(tableScreenshotGraphics);
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
tableHeader.printAll(tableScreenshotGraphics);
}
});
} catch (Exception e) {
}
}
tableScreenshotGraphics.translate(0, tableHeaderSize.height);
final Component printSrc = source;
// Component.printAll has to run in AWT Thread to print component contents correctly
if (SwingUtilities.isEventDispatchThread()) {
printSrc.printAll(tableScreenshotGraphics);
} else {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
printSrc.printAll(tableScreenshotGraphics);
}
});
} catch (Exception e) {
}
}
return tableScreenshot;
}
private static BufferedImage createGeneralComponentScreenshot(Component component) {
Component source;
Dimension sourceSize;
if (component instanceof JViewport) {
JViewport viewport = (JViewport) component;
Component contents = viewport.getView();
if (contents.getSize().height > viewport.getSize().height) {
source = component;
sourceSize = component.getSize();
} else {
source = contents;
sourceSize = contents.getSize();
}
} else {
source = component;
sourceSize = component.getSize();
}
BufferedImage componentScreenshot = new BufferedImage(sourceSize.width, sourceSize.height, BufferedImage.TYPE_INT_RGB);
Graphics componentScreenshotGraphics = componentScreenshot.getGraphics();
source.printAll(componentScreenshotGraphics);
return componentScreenshot;
}
public static void runInEventDispatchThread(final Runnable r) {
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
SwingUtilities.invokeLater(r);
}
}
public static void runInEventDispatchThreadAndWait(final Runnable r) {
if (SwingUtilities.isEventDispatchThread()) {
r.run();
} else {
try {
SwingUtilities.invokeAndWait(r);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static BufferedImage createComponentScreenshot(final Component component) {
final BufferedImage[] result = new BufferedImage[1];
final Runnable screenshotPerformer = new Runnable() {
public void run() {
if (component instanceof JTable || (component instanceof JViewport && ((JViewport) component).getView() instanceof JTable)) {
result[0] = createTableScreenshot(component);
} else {
result[0] = createGeneralComponentScreenshot(component);
}
}
};
try {
if (SwingUtilities.isEventDispatchThread()) {
screenshotPerformer.run();
} else {
SwingUtilities.invokeAndWait(screenshotPerformer);
}
} catch (Exception e) {
return null;
}
return result[0];
}
}