package be.nikiroo.utils.ui; import java.awt.Color; import java.awt.Component; import java.awt.Desktop; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.RadialGradientPaint; import java.awt.RenderingHints; import java.io.IOException; import java.net.URISyntaxException; import javax.swing.JComponent; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import be.nikiroo.fanfix.Instance; import be.nikiroo.utils.Version; import be.nikiroo.utils.VersionCheck; /** * Some Java Swing utilities. * * @author niki */ public class UIUtils { /** * Set a fake "native Look & Feel" for the application if possible * (check for the one currently in use, then try GTK). *
* Must be called prior to any GUI work. * * @return TRUE if it succeeded */ static public boolean setLookAndFeel() { // native look & feel String noLF = "javax.swing.plaf.metal.MetalLookAndFeel"; String lf = UIManager.getSystemLookAndFeelClassName(); if (lf.equals(noLF)) lf = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; return setLookAndFeel(lf); } /** * Switch to the given Look & Feel for the application if possible * (check for the one currently in use, then try GTK). *
* Must be called prior to any GUI work. * * @param laf * the Look & Feel to use * * @return TRUE if it succeeded */ static public boolean setLookAndFeel(String laf) { try { UIManager.setLookAndFeel(laf); return true; } catch (InstantiationException e) { } catch (ClassNotFoundException e) { } catch (UnsupportedLookAndFeelException e) { } catch (IllegalAccessException e) { } return false; } /** * Draw a 3D-looking ellipse at the given location, if the given * {@link Graphics} object is compatible (with {@link Graphics2D}); draw a * simple ellipse if not. * * @param g * the {@link Graphics} to draw on * @param color * the base colour * @param x * the X coordinate * @param y * the Y coordinate * @param width * the width radius * @param height * the height radius */ static public void drawEllipse3D(Graphics g, Color color, int x, int y, int width, int height) { drawEllipse3D(g, color, x, y, width, height, true); } /** * Draw a 3D-looking ellipse at the given location, if the given * {@link Graphics} object is compatible (with {@link Graphics2D}); draw a * simple ellipse if not. * * @param g * the {@link Graphics} to draw on * @param color * the base colour * @param x * the X coordinate of the upper left corner * @param y * the Y coordinate of the upper left corner * @param width * the width radius * @param height * the height radius * @param fill * fill the content of the ellipse */ static public void drawEllipse3D(Graphics g, Color color, int x, int y, int width, int height, boolean fill) { if (g instanceof Graphics2D) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Retains the previous state Paint oldPaint = g2.getPaint(); // Base shape g2.setColor(color); if (fill) { g2.fillOval(x, y, width, height); } else { g2.drawOval(x, y, width, height); } // Compute dark/bright colours Paint p = null; Color dark = color.darker().darker(); Color bright = color.brighter().brighter(); Color darkEnd = new Color(dark.getRed(), dark.getGreen(), dark.getBlue(), 0); Color darkPartial = new Color(dark.getRed(), dark.getGreen(), dark.getBlue(), 64); Color brightEnd = new Color(bright.getRed(), bright.getGreen(), bright.getBlue(), 0); // Adds shadows at the bottom left p = new GradientPaint(0, height, dark, width, 0, darkEnd); g2.setPaint(p); if (fill) { g2.fillOval(x, y, width, height); } else { g2.drawOval(x, y, width, height); } // Adds highlights at the top right p = new GradientPaint(width, 0, bright, 0, height, brightEnd); g2.setPaint(p); if (fill) { g2.fillOval(x, y, width, height); } else { g2.drawOval(x, y, width, height); } // Darken the edges p = new RadialGradientPaint(x + width / 2f, y + height / 2f, Math.min(width / 2f, height / 2f), new float[] { 0f, 1f }, new Color[] { darkEnd, darkPartial }, RadialGradientPaint.CycleMethod.NO_CYCLE); g2.setPaint(p); if (fill) { g2.fillOval(x, y, width, height); } else { g2.drawOval(x, y, width, height); } // Adds inner highlight at the top right p = new RadialGradientPaint(x + 3f * width / 4f, y + height / 4f, Math.min(width / 4f, height / 4f), new float[] { 0.0f, 0.8f }, new Color[] { bright, brightEnd }, RadialGradientPaint.CycleMethod.NO_CYCLE); g2.setPaint(p); if (fill) { g2.fillOval(x * 2, y, width, height); } else { g2.drawOval(x * 2, y, width, height); } // Reset original paint g2.setPaint(oldPaint); } else { g.setColor(color); if (fill) { g.fillOval(x, y, width, height); } else { g.drawOval(x, y, width, height); } } } /** * Add a {@link JScrollPane} around the given panel and use a sensible (for * me) increment for the mouse wheel. * * @param pane * the panel to wrap in a {@link JScrollPane} * @param allowHorizontal * allow horizontal scrolling (not always desired) * * @return the {@link JScrollPane} */ static public JScrollPane scroll(JComponent pane, boolean allowHorizontal) { return scroll(pane, allowHorizontal, true); } /** * Add a {@link JScrollPane} around the given panel and use a sensible (for * me) increment for the mouse wheel. * * @param pane * the panel to wrap in a {@link JScrollPane} * @param allowHorizontal * allow horizontal scrolling (not always desired) * @param allowVertical * allow vertical scrolling (usually yes, but sometimes you only * want horizontal) * * @return the {@link JScrollPane} */ static public JScrollPane scroll(JComponent pane, boolean allowHorizontal, boolean allowVertical) { JScrollPane scroll = new JScrollPane(pane); scroll.getVerticalScrollBar().setUnitIncrement(16); scroll.getHorizontalScrollBar().setUnitIncrement(16); if (!allowHorizontal) { scroll.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); } if (!allowVertical) { scroll.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_NEVER); } return scroll; } /** * Show a confirmation message to the user to show him the changes since * last version. *
* HTML 3.2 supported, links included (the user browser will be launched if * possible). *
* If this is already the latest version, a message will still be displayed.
*
* @param parentComponent
* determines the {@link java.awt.Frame} in which the dialog is
* displayed; if null
, or if the
* parentComponent
has no {@link java.awt.Frame}, a
* default {@link java.awt.Frame} is used
* @param updates
* the new version
* @param introText
* an introduction text before the list of changes
* @param title
* the title of the dialog
*
* @return TRUE if the user clicked on OK, false if the dialog was dismissed
*/
static public boolean showUpdatedDialog(Component parentComponent,
VersionCheck updates, String introText, String title) {
StringBuilder builder = new StringBuilder();
final JEditorPane updateMessage = new JEditorPane("text/html", "");
if (introText != null && !introText.isEmpty()) {
builder.append(introText);
builder.append("
");
builder.append("
");
}
for (Version v : updates.getNewer()) {
builder.append("\t" //
+ "Version " + v.toString() //
+ "");
builder.append("
");
builder.append("