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); } }