package com.limegroup.gnutella.gui; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; import javax.swing.UIManager; import sun.java2d.SunGraphics2D; import apple.laf.AquaImageFactory; import apple.laf.AquaTabbedPaneUI; /** * A progress-bar tab for use with OSX on Java 1.4. */ public class AquaTab extends AquaTabbedPaneUI { private static final int TRANSLUCENCY = 0x80000000; private static final int LIME_GREEN = 0x00179524; // ARGB /* * TODO: Check on every new Mac OS X release if Apple * has changed the shape of the Tabs and if adjustemns * are necessary (and if vertical offsets are necessary). * It should look OK without the offsets though! This is * just finetuning! * * Current: OSX 10.3 and 10.4 */ private static final int TOP_OFFSET = 3; private static final int BOTTOM_OFFSET = 1; public AquaTab() { } /** * Extended to paint the progress bar. */ protected void paintContents(Graphics g, int tabPlacement, int selTab, Rectangle tabRect, Rectangle iconRect, Rectangle tabRect2, boolean isSelected) { // The size check is necessary because an extra tab // is created that lets the user choose which hidden // tabs should be displayed. This tab has no component // and is not really part of the JTabbedPane, and thus // causes an IndexOutOfBoundsException when getting the // component. The extra tab is only created when there // are too many tabs to be displayed in a single tab run. if(selTab < tabPane.getTabCount()) { // The basic idea is to draw an offscreen image of the Tab // and to use its alpha mask to draw the pseudo progress // indicator which will have the same shape as the actual // Tab. Here and there a bit translucency and it looks // like as if the progress indicator is part of the Tab // but it's actually drawn on the top of it final int w = tabRect.width; final int h = tabRect.height; BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); // Should be always the case but who knows? if (g2 instanceof SunGraphics2D) { //final int VERTICAL = 0; final int HONIZONTAL = 1; boolean selected = false;//isSelected; boolean hidden = false; boolean active = true; boolean leftCap = (selTab == 0); boolean rightCap = (selTab == tabPane.getTabCount()-1); boolean focused = false; // Draw the Tab AquaImageFactory.drawTab((SunGraphics2D)g2, 0, 0, w, h, HONIZONTAL, selected, hidden, false, active, leftCap, rightCap, focused, false); } g2.dispose(); img.flush(); DataBuffer src = img.getAlphaRaster().getDataBuffer(); long currentTime = System.currentTimeMillis(); ProgTabUIFactory.Progressor prog = (ProgTabUIFactory.Progressor)tabPane.getComponentAt(selTab); double percent = prog.calculatePercentage(currentTime); if(percent > 1) percent = 1.0; BufferedImage progress = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); DataBuffer dst = progress.getAlphaRaster().getDataBuffer(); final int p = (int)(w * percent); for(int y = TOP_OFFSET; y < (h-BOTTOM_OFFSET); y++) { for(int x = 0; x < p; x++) { int index = (y*w)+x; int value = src.getElem(index); dst.setElem(index, (value & TRANSLUCENCY) | getColor()); } } progress.flush(); g.drawImage(progress, tabRect.x, tabRect.y, null); } super.paintContents(g, tabPlacement, selTab, tabRect, iconRect, tabRect2, isSelected); } private static int getColor() { Color selectionBackground = UIManager.getDefaults().getColor("TextField.selectionBackground"); if (selectionBackground == null) return LIME_GREEN; // Make it a bit darker as cobinations like Aqua // theme (Blue) and Blue highlight color are barely // visible. Same for Graphite and Graphite or Silver! selectionBackground = selectionBackground.darker(); return (selectionBackground.getRed() << 16) | (selectionBackground.getGreen() << 8) | (selectionBackground.getBlue()); } }