/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Tiny Look and Feel * * * * (C) Copyright 2003 - 2007 Hans Bickel * * * * For licensing information and credits, please refer to the * * comment in file de.muntjak.tinylookandfeel.TinyLookAndFeel * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package de.muntjak.tinylookandfeel; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import javax.swing.*; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicGraphicsUtils; import javax.swing.plaf.basic.BasicProgressBarUI; import de.muntjak.tinylookandfeel.controlpanel.*; /** * TinyProgressBarUI * * @version 1.1 * @author Hans Bickel */ public class TinyProgressBarUI extends BasicProgressBarUI { static HashMap cache = new HashMap(); /* "Override" the dimensions from BasicProgressBarUI */ private static final Dimension PREFERRED_YQ_HORIZONTAL = new Dimension(146, 7); private static final Dimension PREFERRED_YQ_VERTICAL = new Dimension(7, 146); private static final Dimension PREFERRED_99_HORIZONTAL = new Dimension(146, 6); private static final Dimension PREFERRED_99_VERTICAL = new Dimension(6, 146); protected Dimension getPreferredInnerHorizontal() { if(Theme.derivedStyle[Theme.style] == Theme.YQ_STYLE) { return PREFERRED_YQ_HORIZONTAL; } return PREFERRED_99_HORIZONTAL; } protected Dimension getPreferredInnerVertical() { if(Theme.derivedStyle[Theme.style] == Theme.YQ_STYLE) { return PREFERRED_YQ_VERTICAL; } return PREFERRED_99_VERTICAL; } /** * Creates the UI delegate for the given component. * * @param mainColor The component to create its UI delegate. * @return The UI delegate for the given component. */ public static ComponentUI createUI(JComponent c) { return new TinyProgressBarUI(); } protected void paintDeterminate(Graphics g, JComponent c) { Insets b = progressBar.getInsets(); // area for border int barRectWidth = progressBar.getWidth() - (b.right + b.left); int barRectHeight = progressBar.getHeight() - (b.top + b.bottom); if(progressBar.getOrientation() == JProgressBar.HORIZONTAL) { int amountFull = getAmountFull(b, barRectWidth, barRectHeight); switch (Theme.derivedStyle[Theme.style]) { case Theme.TINY_STYLE : drawTinyHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); break; case Theme.W99_STYLE : drawWinHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); break; case Theme.YQ_STYLE : drawXpHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); break; } // Deal with possible text painting if(progressBar.isStringPainted()) { g.setFont(c.getFont()); paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b); } } else { // VERTICAL int amountFull = getAmountFull(b, barRectWidth, barRectHeight); switch (Theme.derivedStyle[Theme.style]) { case Theme.TINY_STYLE : drawTinyVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); break; case Theme.W99_STYLE : drawWinVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); break; case Theme.YQ_STYLE : drawXpVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); break; } // Deal with possible text painting if(progressBar.isStringPainted()) { g.setFont(c.getFont()); paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b); } } } private void drawTinyHorzProgress(Graphics g, int x, int y, int barRectWidth, int barRectHeight, int amountFull) { } private void drawWinHorzProgress(Graphics g, int x, int y, int w, int h, int amountFull) { // paint the track g.translate(x, y); g.setColor(Theme.progressTrackColor[Theme.style].getColor()); g.fillRect(1, 1, w - 1, h - 1); g.setColor(Theme.progressColor[Theme.style].getColor()); int mx = 0; while(mx < amountFull) { if(mx + 6 > w) { // paint partially g.fillRect(mx, 0, w - mx, h); } else { g.fillRect(mx, 0, 6, h); } mx += 8; } g.translate(-x, -y); } // draw determinate private void drawXpHorzProgress(Graphics g, int x, int y, int w, int h, int amountFull) { g.translate(x, y); // paint the track if(!progressBar.isOpaque()) { g.setColor(progressBar.getBackground()); g.fillRect(0, 0, w, h); } ProgressKey key = new ProgressKey( progressBar.getForeground(), true, h); Object value = cache.get(key); if(value == null) { // create new image Image img = new BufferedImage(6, h, BufferedImage.TYPE_INT_ARGB); Graphics imgGraphics = img.getGraphics(); // draw into image graphics Color c = progressBar.getForeground(); Color c2 = ColorRoutines.lighten(c, 15); Color c3 = ColorRoutines.lighten(c, 35); Color c4 = ColorRoutines.lighten(c, 60); imgGraphics.setColor(c4); imgGraphics.drawLine(0, 0, 5, 0); imgGraphics.drawLine(0, h - 1, 5, h - 1); imgGraphics.setColor(c3); imgGraphics.drawLine(0, 1, 5, 1); imgGraphics.drawLine(0, h - 2, 5, h - 2); imgGraphics.setColor(c2); imgGraphics.drawLine(0, 2, 5, 2); imgGraphics.drawLine(0, h - 3, 5, h - 3); imgGraphics.setColor(c); imgGraphics.fillRect(0, 3, 6, h - 6); // dispose of image graphics imgGraphics.dispose(); cache.put(key, img); value = img; } int mx = 0; while(mx < amountFull) { if(mx + 6 > w) { // paint partially g.drawImage((Image)value, mx, 0, w - mx, h, progressBar); } else { g.drawImage((Image)value, mx, 0, progressBar); } mx += 8; } g.translate(-x, -y); } private void drawTinyVertProgress(Graphics g, int x, int y, int barRectWidth, int barRectHeight, int amountFull) { } private void drawWinVertProgress(Graphics g, int x, int y, int w, int h, int amountFull) { // paint the track g.translate(x, y); g.setColor(Theme.progressTrackColor[Theme.style].getColor()); g.fillRect(1, 1, w - 1, h - 1); g.setColor(Theme.progressColor[Theme.style].getColor()); int my = 0; while(my < amountFull) { if(my + 6 > h) { // paint partially g.fillRect(0, 0, w, h - my); } else { g.fillRect(0, h - my - 6, w, 6); } my += 8; } g.translate(-x, -y); } // draw determinate private void drawXpVertProgress(Graphics g, int x, int y, int w, int h, int amountFull) { g.translate(x, y); // paint the track if(!progressBar.isOpaque()) { g.setColor(progressBar.getBackground()); g.fillRect(0, 0, w, h); } ProgressKey key = new ProgressKey( progressBar.getForeground(), false, w); Object value = cache.get(key); if(value == null) { // create new image Image img = new BufferedImage(w, 6, BufferedImage.TYPE_INT_ARGB); Graphics imgGraphics = img.getGraphics(); // draw into image graphics Color c = progressBar.getForeground(); Color c2 = ColorRoutines.lighten(c, 15); Color c3 = ColorRoutines.lighten(c, 35); Color c4 = ColorRoutines.lighten(c, 60); imgGraphics.setColor(c4); imgGraphics.drawLine(0, 0, 0, 5); imgGraphics.drawLine(w - 1, 0, w - 1, 5); imgGraphics.setColor(c3); imgGraphics.drawLine(1, 0, 1, 5); imgGraphics.drawLine(w - 2, 0, w - 2, 5); imgGraphics.setColor(c2); imgGraphics.drawLine(2, 0, 2, 5); imgGraphics.drawLine(w - 3, 0, w - 3, 5); imgGraphics.setColor(c); imgGraphics.fillRect(3, 0, w - 6, 6); // dispose of image graphics imgGraphics.dispose(); cache.put(key, img); value = img; } // paints bottom to top... int my = 0; while(my < amountFull) { if(my + 6 > h) { // paint partially g.drawImage((Image)value, 0, 0, w, h - my, progressBar); } else { g.drawImage((Image)value, 0, h - my - 6, progressBar); } my += 8; } g.translate(-x, -y); } protected void paintIndeterminate(Graphics g, JComponent c) { Insets b = progressBar.getInsets(); // area for border int barRectWidth = progressBar.getWidth() - (b.right + b.left); int barRectHeight = progressBar.getHeight() - (b.top + b.bottom); Rectangle boxRect = new Rectangle(); try { boxRect = getBox(boxRect); } catch (NullPointerException ignore) {} if(progressBar.getOrientation() == JProgressBar.HORIZONTAL) { switch (Theme.derivedStyle[Theme.style]) { case Theme.TINY_STYLE : drawTinyHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); break; case Theme.W99_STYLE : drawWinHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); break; case Theme.YQ_STYLE : drawXpHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); break; } } else { switch (Theme.derivedStyle[Theme.style]) { case Theme.TINY_STYLE : drawTinyVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); break; case Theme.W99_STYLE : drawWinVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); break; case Theme.YQ_STYLE : drawXpVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); break; } } // Deal with possible text painting if(progressBar.isStringPainted()) { if(progressBar.getOrientation() == JProgressBar.HORIZONTAL) { paintString(g, b.left, b.top, barRectWidth, barRectHeight, boxRect.x, boxRect.width, b); } else { paintString(g, b.left, b.top, barRectWidth, barRectHeight, boxRect.y, boxRect.height, b); } } } private void paintString(Graphics g, int x, int y, int width, int height, int fillStart, int amountFull, Insets b) { if(!(g instanceof Graphics2D)) { return; } Graphics2D g2 = (Graphics2D)g; String progressString = progressBar.getString(); g2.setFont(progressBar.getFont()); Point renderLocation = getStringPlacement(g2, progressString, x, y, width, height); Rectangle oldClip = g2.getClipBounds(); if(progressBar.getOrientation() == JProgressBar.HORIZONTAL) { g2.setColor(getSelectionBackground()); g2.drawString(progressString, renderLocation.x, renderLocation.y); g2.setColor(getSelectionForeground()); g2.clipRect(fillStart, y, amountFull, height); g.drawString(progressString, renderLocation.x, renderLocation.y); } else { // VERTICAL g2.setColor(getSelectionBackground()); AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2); g2.setFont(progressBar.getFont().deriveFont(rotate)); renderLocation = getStringPlacement(g2, progressString, x, y, width, height); g2.drawString(progressString, renderLocation.x, renderLocation.y); g2.setColor(getSelectionForeground()); g2.clipRect(x, fillStart, width, amountFull); g2.drawString(progressString, renderLocation.x, renderLocation.y); } g2.setClip(oldClip); } /* * Inserted this to fix a bug that came with 1.4.2_02 and caused NPE at * javax.swing.plaf.basic.BasicProgressBarUI.updateSizes(BasicProgressBarUI.java:439). * * @see javax.swing.plaf.basic.BasicProgressBarUI#paintString(java.awt.Graphics, int, int, int, int, int, java.awt.Insets) */ protected void paintString(Graphics g, int x, int y, int width, int height, int amountFull, Insets b) { Rectangle boxRect = new Rectangle(); // * try { // * The Fix boxRect = getBox(boxRect); // * } catch (NullPointerException ignore) {} // * if(progressBar.getOrientation() == JProgressBar.HORIZONTAL) { if(progressBar.getComponentOrientation().isLeftToRight()) { if(progressBar.isIndeterminate()) { paintString(g, x, y, width, height, boxRect.x, boxRect.width, b); } else { paintString(g, x, y, width, height, x, amountFull, b); } } else { paintString(g, x, y, width, height, x + width - amountFull, amountFull, b); } } else { if(progressBar.isIndeterminate()) { paintString(g, x, y, width, height, boxRect.y, boxRect.height, b); } else { paintString(g, x, y, width, height, y + height - amountFull, amountFull, b); } } } private void drawTinyHorzProgress(Graphics g, int x, int y, int barRectWidth, int barRectHeight, Rectangle boxRect) { } private void drawWinHorzProgress(Graphics g, int x, int y, int w, int h, Rectangle boxRect) { // paint the track g.setColor(Theme.progressTrackColor[Theme.style].getColor()); g.fillRect(x + 1, y + 1, w - 1, h - 1); g.translate(boxRect.x, boxRect.y); g.setColor(Theme.progressColor[Theme.style].getColor()); int mx = 0; while (mx + 6 < boxRect.width) { g.fillRect(mx, 0, 6, h); mx += 8; } g.translate(-boxRect.x, -boxRect.y); } // draw indeterminate private void drawXpHorzProgress(Graphics g, int x, int y, int w, int h, Rectangle boxRect) { // paint the track if(!progressBar.isOpaque()) { g.setColor(progressBar.getBackground()); g.fillRect(x, y, w, h); } g.translate(boxRect.x, boxRect.y); ProgressKey key = new ProgressKey( progressBar.getForeground(), true, h); Object value = cache.get(key); if(value == null) { // create new image Image img = new BufferedImage(6, h, BufferedImage.TYPE_INT_ARGB); Graphics imgGraphics = img.getGraphics(); // draw into image graphics Color c = progressBar.getForeground(); Color c2 = ColorRoutines.lighten(c, 15); Color c3 = ColorRoutines.lighten(c, 35); Color c4 = ColorRoutines.lighten(c, 60); imgGraphics.setColor(c4); imgGraphics.drawLine(0, 0, 5, 0); imgGraphics.drawLine(0, h - 1, 5, h - 1); imgGraphics.setColor(c3); imgGraphics.drawLine(0, 1, 5, 1); imgGraphics.drawLine(0, h - 2, 5, h - 2); imgGraphics.setColor(c2); imgGraphics.drawLine(0, 2, 5, 2); imgGraphics.drawLine(0, h - 3, 5, h - 3); imgGraphics.setColor(c); imgGraphics.fillRect(0, 3, 6, h - 6); // dispose of image graphics imgGraphics.dispose(); cache.put(key, img); value = img; } int mx = 0; while(mx + 6 < boxRect.width) { g.drawImage((Image)value, mx, 0, progressBar); mx += 8; } g.translate(-boxRect.x, -boxRect.y); } private void drawTinyVertProgress(Graphics g, int x, int y, int w, int h, Rectangle boxRect) { } private void drawWinVertProgress(Graphics g, int x, int y, int w, int h, Rectangle boxRect) { // paint the track g.setColor(Theme.progressTrackColor[Theme.style].getColor()); g.fillRect(x + 1, y + 1, w - 1, h - 1); g.translate(boxRect.x, boxRect.y); g.setColor(Theme.progressColor[Theme.style].getColor()); int my = 0; while (my + 6 < boxRect.height) { g.fillRect(0, my, w, 6); my += 8; } g.translate(-boxRect.x, -boxRect.y); } // draw indeterminate private void drawXpVertProgress(Graphics g, int x, int y, int w, int h, Rectangle boxRect) { // paint the track if(!progressBar.isOpaque()) { g.setColor(progressBar.getBackground()); g.fillRect(x, y, w, h); } g.translate(boxRect.x, boxRect.y); ProgressKey key = new ProgressKey( progressBar.getForeground(), false, w); Object value = cache.get(key); if(value == null) { // create new image Image img = new BufferedImage(w, 6, BufferedImage.TYPE_INT_ARGB); Graphics imgGraphics = img.getGraphics(); // draw into image graphics Color c = progressBar.getForeground(); Color c2 = ColorRoutines.lighten(c, 15); Color c3 = ColorRoutines.lighten(c, 35); Color c4 = ColorRoutines.lighten(c, 60); imgGraphics.setColor(c4); imgGraphics.drawLine(0, 0, 0, 5); imgGraphics.drawLine(w - 1, 0, w - 1, 5); imgGraphics.setColor(c3); imgGraphics.drawLine(1, 0, 1, 5); imgGraphics.drawLine(w - 2, 0, w - 2, 5); imgGraphics.setColor(c2); imgGraphics.drawLine(2, 0, 2, 5); imgGraphics.drawLine(w - 3, 0, w - 3, 5); imgGraphics.setColor(c); imgGraphics.fillRect(3, 0, w - 6, 6); // dispose of image graphics imgGraphics.dispose(); cache.put(key, img); value = img; } int my = 0; while(my + 6 < boxRect.height) { g.drawImage((Image)value, 0, my, progressBar); my += 8; } g.translate(-boxRect.x, -boxRect.y); } protected Color getSelectionForeground() { return Theme.progressSelectForeColor[Theme.style].getColor(); } protected Color getSelectionBackground() { return Theme.progressSelectBackColor[Theme.style].getColor(); } protected void installDefaults() { // Note: Omitting the following line was a bug from v1.3.01 until v1.3.04 // Note: The following method turned out to be new in 1.5. Therefore // replaced with progressBar.setOpaque(true) //LookAndFeel.installProperty(progressBar, "opaque", Boolean.TRUE); // removed again in 1.3.7 (because opaque progress bar // fills bounds with track [background] color) //progressBar.setOpaque(true); LookAndFeel.installBorder(progressBar, "ProgressBar.border"); LookAndFeel.installColorsAndFont(progressBar, "ProgressBar.background", "ProgressBar.foreground", "ProgressBar.font"); } /* * ProgressKey is used as key in the cache HashMap. * Overrides equals() and hashCode(). */ static class ProgressKey { private Color c; private boolean horizontal; private int size; ProgressKey(Color c, boolean horizontal, int size) { this.c = c; this.horizontal = horizontal; this.size = size; } public boolean equals(Object o) { if(o == null) return false; if(!(o instanceof ProgressKey)) return false; ProgressKey other = (ProgressKey)o; return size == other.size && horizontal == other.horizontal && c.equals(other.c); } public int hashCode() { return c.hashCode() * (horizontal ? 1 : 2) * size; } } }