package com.illumina.basespace.igv.ui;
import java.awt.AWTEvent;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.List;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;
/**
*
* @author bking
*/
public class BusyGlassPaneRenderer extends javax.swing.JPanel
{
private static final float[] GRADIENT_FRACTIONS = new float[] { 0.0f, 0.499f, 0.5f, 1.0f };
private static final Color[] GRADIENT_COLORS = new Color[] { Color.GRAY, Color.DARK_GRAY, Color.BLACK, Color.GRAY };
private static final Color GRADIENT_COLOR2 = Color.WHITE;
private static final Color GRADIENT_COLOR1 = Color.GRAY;
private JRootPane pane;
private Component overComponent;
private double progress = 0;
private String text = "Working...";
private double progressMax = 100;
private int barHeight = 10;
private static final int DEFAULT_MAX = 100;
private boolean blockInput = true;
protected EventCapture listener;
public BusyGlassPaneRenderer(Component c, boolean blockInput)
{
this(c, DEFAULT_MAX, null);
}
public BusyGlassPaneRenderer(Component c, String initalText, boolean blockInput)
{
this(c, DEFAULT_MAX, initalText, blockInput);
}
public BusyGlassPaneRenderer(Component c, double progressMax)
{
this(c, progressMax, null);
}
public BusyGlassPaneRenderer(Component c, double progressMax, String initialText)
{
this(c, progressMax, null, true);
}
public BusyGlassPaneRenderer(Component c, double progressMax, String initialText, boolean blockInput)
{
this.blockInput = blockInput;
setOpaque(false);
setLayout(new java.awt.GridBagLayout());
this.pane = SwingUtilities.getRootPane(c);
if (this.pane == null) return;
this.overComponent = c;
if (initialText != null) this.text = initialText;
this.progressMax = progressMax;
this.pane.setGlassPane(this);
setBackground(Color.WHITE);
setFont(new Font("Default", Font.BOLD, 14));
listener = new EventCapture();
}
public int getBarHeight()
{
return barHeight;
}
public void setBarHeight(int barHeight)
{
this.barHeight = barHeight;
}
public void showHint()
{
Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.MOUSE_EVENT_MASK);
if (pane != null) pane.getGlassPane().setVisible(true);
}
public void dispose()
{
if (pane != null)
{
pane.getGlassPane().setVisible(false);
}
Toolkit.getDefaultToolkit().removeAWTEventListener(listener);
}
public void process(List<ProgressReport> chunks)
{
for (ProgressReport chunk : chunks)
{
if (chunk.getProgress() > -1) progress = chunk.getProgress();
if (chunk.getText() != null) text = chunk.getText();
}
if (overComponent == null)
{
return;
}
Point loc = overComponent.getLocation();
repaint(loc.x, loc.y, overComponent.getWidth(), overComponent.getHeight());
}
public boolean supportsSynchronous()
{
return false;
}
public boolean supportsAsynchronous()
{
return true;
}
public void supportCancel(boolean support)
{
}
// </editor-fold>
private Rectangle getOverComponentBounds()
{
Point loc = overComponent.getLocation();
loc = SwingUtilities.convertPoint(overComponent, loc, pane);
return new Rectangle(loc.x, loc.y, overComponent.getWidth(), overComponent.getHeight());
}
public double getProgressMax()
{
return progressMax;
}
public void setProgressMax(double progressMax)
{
this.progressMax = progressMax;
}
@Override
protected void paintComponent(Graphics g)
{
Rectangle bounds = getOverComponentBounds();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// sets a 65% translucent composite
AlphaComposite alpha = AlphaComposite.SrcOver.derive(0.65f);
Composite composite = g2.getComposite();
g2.setComposite(alpha);
// fills the background
g2.setColor(getBackground());
g2.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
FontMetrics metrics = g.getFontMetrics();
Rectangle2D textRect = metrics.getStringBounds(this.text, g2);
int x = (int) (bounds.x + ((bounds.getWidth() - textRect.getWidth()) / 2));
int y = (int) (bounds.y + ((bounds.getHeight() - textRect.getHeight()) / 2));
// draws the text
g2.setColor(Color.BLACK);
g2.drawString(this.text, x, y);
// goes to the position of the progress bar
y += metrics.getDescent();
int barWidth = (int) (bounds.getWidth() * .50);
x = (int) (bounds.x + ((bounds.getWidth() - barWidth) / 2));
// computes the size of the progress indicator
int w = (int) (barWidth * ((float) progress / progressMax));
int h = getBarHeight();
// draws the content of the progress bar
Paint paint = g2.getPaint();
// bar's background
Paint gradient = new GradientPaint(x, y, GRADIENT_COLOR1, x, y + h, GRADIENT_COLOR2);
g2.setPaint(gradient);
g2.fillRect(x, y, barWidth, getBarHeight());
// actual progress
gradient = new LinearGradientPaint(x, y, x, y + h, GRADIENT_FRACTIONS, GRADIENT_COLORS);
g2.setPaint(gradient);
g2.fillRect(x, y, w, h);
g2.setPaint(paint);
// draws the progress bar border
g2.drawRect(x, y, barWidth, getBarHeight());
g2.setComposite(composite);
}
protected class EventCapture implements AWTEventListener
{
@Override
public void eventDispatched(AWTEvent event)
{
if (event instanceof MouseEvent)
{
MouseEvent evt = (MouseEvent) event;
Point loc = overComponent.getLocationOnScreen();
Rectangle componentBounds = new Rectangle(loc.x, loc.y, overComponent.getWidth(), overComponent.getHeight());
Point mousePoint = evt.getPoint();
SwingUtilities.convertPointToScreen(mousePoint, pane);
if (componentBounds.contains(mousePoint))
{
if (blockInput) evt.consume();
}
}
}
}
}