package com.limegroup.gnutella.gui;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.CellRendererPane;
import javax.swing.JProgressBar;
import javax.swing.JTabbedPane;
import javax.swing.plaf.TabbedPaneUI;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import javax.swing.plaf.metal.MetalTabbedPaneUI;
public final class ProgTabUIFactory {
private ProgTabUIFactory() {}
/**
* The classes for each specific UI we know how to handle.
*/
private static final Class aquaUI;
private static final Class windowsUI;
private static final Class metalUI;
private static final Class basicUI;
static {
aquaUI = loadClass("apple.laf.AquaTabbedPaneUI");
windowsUI =
loadClass("com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI");
metalUI = javax.swing.plaf.metal.MetalTabbedPaneUI.class;
basicUI = javax.swing.plaf.basic.BasicTabbedPaneUI.class;
}
/**
* Load the specified class -- if it couldn't load, return null.
*/
private static final Class loadClass(String toLoad) {
try {
return Class.forName(toLoad);
} catch(ClassNotFoundException cfnfe) {
return null;
}
}
/**
* Creates a new instance of the class if it could load.
* If it couldn't be loaded, return the default UI.
*/
private static TabbedPaneUI createNewUI(String toLoad,
TabbedPaneUI def) {
Class clazz = loadClass(toLoad);
if( clazz == null )
return def;
try {
return (TabbedPaneUI)clazz.newInstance();
} catch(IllegalAccessException iae) {
return def;
} catch(InstantiationException iae) {
return def;
} catch(ExceptionInInitializerError eiie) {
return def;
} catch(SecurityException se) {
return def;
} catch(ClassCastException cce) {
return def;
}
}
/**
* Update the UI of this JTabbedPane to contain a progress bar
*/
public static void extendUI(JTabbedPane pane) {
TabbedPaneUI oldUI = pane.getUI();
TabbedPaneUI newUI = oldUI;
if( aquaUI != null && aquaUI.isInstance(oldUI) )
newUI = createNewUI("com.limegroup.gnutella.gui.AquaTab", newUI);
else if( windowsUI != null && windowsUI.isInstance(oldUI) )
newUI = createNewUI("com.limegroup.gnutella.gui.WinTab", newUI);
else if( metalUI != null && metalUI.isInstance(oldUI) )
newUI = new MetalTab();
// Note that this last check is an == check.
// This is because lots of UIs are going to extend from BasicUI
// and we only want to use the BasicTab if we are positive that
// the actual tab is using a BasicUI.
else if( oldUI.getClass() == basicUI )
newUI = new BasicTab();
pane.setUI(newUI);
}
/**
* For use with Windows L&F's on Java 1.3 and below.
* Renders a shade darker than the background over the
* entire tab, before the text is drawn.
*/
private static class BasicTab extends BasicTabbedPaneUI {
protected void paintTabBackground(Graphics g, int tabPlacement,
int tabIndex,
int x, int y, int w, int h,
boolean isSelected) {
super.paintTabBackground(g, tabPlacement, tabIndex,
x, y, w, h, isSelected);
Color darker = tabPane.getBackgroundAt(tabIndex).darker();
g.setColor(darker);
long currentTime = System.currentTimeMillis();
Progressor p = (Progressor)tabPane.getComponentAt(tabIndex);
double percent = p.calculatePercentage(currentTime);
if( percent > 1 )
percent = 1.0;
g.fillRect(x+1, y+1, (int)((w-3)*percent), h-1);
}
}
/**
* For use with the Metal L&F.
* Draws a ProgressBar, starting with the left of the text area
* over to the right-side of the whole tab. Draws the text
* ontop of the progressbar.
*/
private static class MetalTab extends MetalTabbedPaneUI {
private final JProgressBar PROGRESS = new JProgressBar();
private final CellRendererPane PANE = new CellRendererPane();
public MetalTab() {
super();
PROGRESS.setMinimum(0);
PROGRESS.setMaximum(100);
PROGRESS.setBorderPainted(false);
PROGRESS.setOpaque(false);
}
protected void paintText(Graphics g, int tabPlacement,
Font font, FontMetrics metrics,
int tabIndex, String title,
Rectangle textRect, boolean isSelected) {
long currentTime = System.currentTimeMillis();
Progressor p = (Progressor)tabPane.getComponentAt(tabIndex);
double percent = p.calculatePercentage(currentTime);
if( percent > 1 )
percent = 1.0;
PROGRESS.setValue((int)(percent * 100));
Rectangle tabRect = tabPane.getBoundsAt(tabIndex);
int x, y, w, h;
x = textRect.x - 4;
y = textRect.y;
w = tabRect.width + tabRect.x - x - 1;
h = tabRect.height + tabRect.y - y;
PANE.paintComponent(g, PROGRESS, tabPane.getParent(),
x, y, w, h);
super.paintText(g, tabPlacement, font, metrics, tabIndex,
title, textRect, isSelected);
}
}
public interface Progressor {
public double calculatePercentage(long currentTime);
}
}