You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
15 KiB
413 lines
15 KiB
/*
|
|
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
package com.sun.java.swing.plaf.windows;
|
|
|
|
import javax.swing.plaf.basic.*;
|
|
import javax.swing.plaf.*;
|
|
import javax.swing.*;
|
|
import java.awt.*;
|
|
|
|
import static com.sun.java.swing.plaf.windows.TMSchema.*;
|
|
import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
|
|
|
|
|
|
/**
|
|
* Windows rendition of the component.
|
|
* <p>
|
|
* <strong>Warning:</strong>
|
|
* Serialized objects of this class will not be compatible with
|
|
* future Swing releases. The current serialization support is appropriate
|
|
* for short term storage or RMI between applications running the same
|
|
* version of Swing. A future release of Swing will provide support for
|
|
* long term persistence.
|
|
*
|
|
* @author Michael C. Albers
|
|
*/
|
|
public class WindowsProgressBarUI extends BasicProgressBarUI
|
|
{
|
|
|
|
private Rectangle previousFullBox;
|
|
private Insets indeterminateInsets;
|
|
|
|
public static ComponentUI createUI(JComponent x) {
|
|
return new WindowsProgressBarUI();
|
|
}
|
|
|
|
|
|
protected void installDefaults() {
|
|
super.installDefaults();
|
|
|
|
if (XPStyle.getXP() != null) {
|
|
LookAndFeel.installProperty(progressBar, "opaque", Boolean.FALSE);
|
|
progressBar.setBorder(null);
|
|
indeterminateInsets = UIManager.getInsets("ProgressBar.indeterminateInsets");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the baseline.
|
|
*
|
|
* @throws NullPointerException {@inheritDoc}
|
|
* @throws IllegalArgumentException {@inheritDoc}
|
|
* @see javax.swing.JComponent#getBaseline(int, int)
|
|
* @since 1.6
|
|
*/
|
|
public int getBaseline(JComponent c, int width, int height) {
|
|
int baseline = super.getBaseline(c, width, height);
|
|
if (XPStyle.getXP() != null && progressBar.isStringPainted() &&
|
|
progressBar.getOrientation() == JProgressBar.HORIZONTAL) {
|
|
FontMetrics metrics = progressBar.
|
|
getFontMetrics(progressBar.getFont());
|
|
int y = progressBar.getInsets().top;
|
|
if (progressBar.isIndeterminate()) {
|
|
y = -1;
|
|
height--;
|
|
}
|
|
else {
|
|
y = 0;
|
|
height -= 3;
|
|
}
|
|
baseline = y + (height + metrics.getAscent() -
|
|
metrics.getLeading() -
|
|
metrics.getDescent()) / 2;
|
|
}
|
|
return baseline;
|
|
}
|
|
|
|
protected Dimension getPreferredInnerHorizontal() {
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp != null) {
|
|
Skin skin = xp.getSkin(progressBar, Part.PP_BAR);
|
|
return new Dimension(
|
|
(int)super.getPreferredInnerHorizontal().getWidth(),
|
|
skin.getHeight());
|
|
}
|
|
return super.getPreferredInnerHorizontal();
|
|
}
|
|
|
|
protected Dimension getPreferredInnerVertical() {
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp != null) {
|
|
Skin skin = xp.getSkin(progressBar, Part.PP_BARVERT);
|
|
return new Dimension(
|
|
skin.getWidth(),
|
|
(int)super.getPreferredInnerVertical().getHeight());
|
|
}
|
|
return super.getPreferredInnerVertical();
|
|
}
|
|
|
|
protected void paintDeterminate(Graphics g, JComponent c) {
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp != null) {
|
|
boolean vertical = (progressBar.getOrientation() == JProgressBar.VERTICAL);
|
|
boolean isLeftToRight = WindowsGraphicsUtils.isLeftToRight(c);
|
|
int barRectWidth = progressBar.getWidth();
|
|
int barRectHeight = progressBar.getHeight()-1;
|
|
// amount of progress to draw
|
|
int amountFull = getAmountFull(null, barRectWidth, barRectHeight);
|
|
|
|
paintXPBackground(g, vertical, barRectWidth, barRectHeight);
|
|
// Paint progress
|
|
if (progressBar.isStringPainted()) {
|
|
// Do not paint the standard stripes from the skin, because they obscure
|
|
// the text
|
|
g.setColor(progressBar.getForeground());
|
|
barRectHeight -= 2;
|
|
barRectWidth -= 2;
|
|
|
|
if (barRectWidth <= 0 || barRectHeight <= 0) {
|
|
return;
|
|
}
|
|
|
|
Graphics2D g2 = (Graphics2D)g;
|
|
g2.setStroke(new BasicStroke((float)(vertical ? barRectWidth : barRectHeight),
|
|
BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
|
if (!vertical) {
|
|
if (isLeftToRight) {
|
|
g2.drawLine(2, barRectHeight / 2 + 1,
|
|
amountFull - 2, barRectHeight / 2 + 1);
|
|
} else {
|
|
g2.drawLine(2 + barRectWidth,
|
|
barRectHeight / 2 + 1,
|
|
2 + barRectWidth - (amountFull - 2),
|
|
barRectHeight / 2 + 1);
|
|
}
|
|
paintString(g, 0, 0, barRectWidth, barRectHeight, amountFull, null);
|
|
} else {
|
|
g2.drawLine(barRectWidth/2 + 1, barRectHeight + 1,
|
|
barRectWidth/2 + 1, barRectHeight + 1 - amountFull + 2);
|
|
paintString(g, 2, 2, barRectWidth, barRectHeight, amountFull, null);
|
|
}
|
|
|
|
} else {
|
|
Skin skin = xp.getSkin(progressBar, vertical ? Part.PP_CHUNKVERT : Part.PP_CHUNK);
|
|
int thickness;
|
|
if (vertical) {
|
|
thickness = barRectWidth - 5;
|
|
} else {
|
|
thickness = barRectHeight - 5;
|
|
}
|
|
|
|
int chunkSize = xp.getInt(progressBar, Part.PP_PROGRESS, null, Prop.PROGRESSCHUNKSIZE, 2);
|
|
int spaceSize = xp.getInt(progressBar, Part.PP_PROGRESS, null, Prop.PROGRESSSPACESIZE, 0);
|
|
int nChunks = (amountFull-4) / (chunkSize + spaceSize);
|
|
|
|
// See if we can squeeze in an extra chunk without spacing after
|
|
if (spaceSize > 0 && (nChunks * (chunkSize + spaceSize) + chunkSize) < (amountFull-4)) {
|
|
nChunks++;
|
|
}
|
|
|
|
for (int i = 0; i < nChunks; i++) {
|
|
if (vertical) {
|
|
skin.paintSkin(g,
|
|
3, barRectHeight - i * (chunkSize + spaceSize) - chunkSize - 2,
|
|
thickness, chunkSize, null);
|
|
} else {
|
|
if (isLeftToRight) {
|
|
skin.paintSkin(g,
|
|
4 + i * (chunkSize + spaceSize), 2,
|
|
chunkSize, thickness, null);
|
|
} else {
|
|
skin.paintSkin(g,
|
|
barRectWidth - (2 + (i+1) * (chunkSize + spaceSize)), 2,
|
|
chunkSize, thickness, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
super.paintDeterminate(g, c);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
* @since 1.6
|
|
*/
|
|
protected void setAnimationIndex(int newValue) {
|
|
super.setAnimationIndex(newValue);
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp != null) {
|
|
if (boxRect != null) {
|
|
// get the full repaint area and add it the
|
|
// previous one so we can erase it
|
|
Rectangle chunk = getFullChunkBounds(boxRect);
|
|
if (previousFullBox != null) {
|
|
chunk.add(previousFullBox);
|
|
}
|
|
progressBar.repaint(chunk);
|
|
} else {
|
|
progressBar.repaint();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
* @since 1.6
|
|
*/
|
|
protected int getBoxLength(int availableLength, int otherDimension) {
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp != null) {
|
|
return 6; // an apparently hard coded value in Windows
|
|
}
|
|
return super.getBoxLength(availableLength, otherDimension);
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
* @since 1.6
|
|
*/
|
|
protected Rectangle getBox(Rectangle r) {
|
|
Rectangle rect = super.getBox(r);
|
|
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp != null) {
|
|
boolean vertical = (progressBar.getOrientation()
|
|
== JProgressBar.VERTICAL);
|
|
Part part = vertical ? Part.PP_BARVERT : Part.PP_BAR;
|
|
Insets ins = indeterminateInsets;
|
|
|
|
int currentFrame = getAnimationIndex();
|
|
int framecount = getFrameCount()/2;
|
|
|
|
int gap = xp.getInt(progressBar, Part.PP_PROGRESS, null,
|
|
Prop.PROGRESSSPACESIZE, 0);
|
|
currentFrame = currentFrame % framecount;
|
|
|
|
// this code adjusts the chunk size to properly account for the
|
|
// size and gap specified in the XP style. It also does it's own
|
|
// box placement for the chunk animation. This is required because
|
|
// the inherited algorithm from BasicProgressBarUI goes back and
|
|
// forth whereas XP only goes in one direction. XP also has ghosted
|
|
// trailing chunks to create the illusion of speed. This code
|
|
// adjusts the pixel length of the animation to account for the
|
|
// trails.
|
|
if (!vertical) {
|
|
rect.y = rect.y + ins.top;
|
|
rect.height = progressBar.getHeight() - ins.top - ins.bottom;
|
|
int len = progressBar.getWidth() - ins.left - ins.right;
|
|
len += (rect.width+gap)*2; // add 2x for the trails
|
|
double delta = (double)(len) / (double)framecount;
|
|
rect.x = (int)(delta * currentFrame) + ins.left;
|
|
} else {
|
|
rect.x = rect.x + ins.left;
|
|
rect.width = progressBar.getWidth() - ins.left - ins.right;
|
|
int len = progressBar.getHeight() - ins.top - ins.bottom;
|
|
len += (rect.height+gap)*2; // add 2x for the trails
|
|
double delta = (double)(len) / (double)framecount;
|
|
rect.y = (int)(delta * currentFrame) + ins.top;
|
|
}
|
|
}
|
|
return rect;
|
|
}
|
|
|
|
|
|
protected void paintIndeterminate(Graphics g, JComponent c) {
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp != null) {
|
|
boolean vertical = (progressBar.getOrientation()
|
|
== JProgressBar.VERTICAL);
|
|
int barRectWidth = progressBar.getWidth();
|
|
int barRectHeight = progressBar.getHeight();
|
|
paintXPBackground(g, vertical, barRectWidth, barRectHeight);
|
|
|
|
// Paint the bouncing box.
|
|
boxRect = getBox(boxRect);
|
|
if (boxRect != null) {
|
|
g.setColor(progressBar.getForeground());
|
|
if (!(g instanceof Graphics2D)) {
|
|
return;
|
|
}
|
|
paintIndeterminateFrame(boxRect, (Graphics2D)g, vertical,
|
|
barRectWidth, barRectHeight);
|
|
if (progressBar.isStringPainted()) {
|
|
if (!vertical) {
|
|
paintString(g, -1, -1, barRectWidth, barRectHeight, 0, null);
|
|
} else {
|
|
paintString(g, 1, 1, barRectWidth, barRectHeight, 0, null);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
super.paintIndeterminate(g, c);
|
|
}
|
|
}
|
|
|
|
private Rectangle getFullChunkBounds(Rectangle box) {
|
|
boolean vertical = (progressBar.getOrientation() == JProgressBar.VERTICAL);
|
|
XPStyle xp = XPStyle.getXP();
|
|
int gap = (xp != null) ? xp.getInt(progressBar, Part.PP_PROGRESS,
|
|
null, Prop.PROGRESSSPACESIZE, 0)
|
|
: 0;
|
|
|
|
if (!vertical) {
|
|
int chunksize = box.width+gap;
|
|
return new Rectangle(box.x-chunksize*2, box.y, chunksize*3, box.height);
|
|
} else {
|
|
int chunksize = box.height+gap;
|
|
return new Rectangle(box.x, box.y-chunksize*2, box.width, chunksize*3);
|
|
}
|
|
}
|
|
|
|
private void paintIndeterminateFrame(Rectangle box, Graphics2D g,
|
|
boolean vertical,
|
|
int bgwidth, int bgheight) {
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp == null) {
|
|
return;
|
|
}
|
|
|
|
// create a new graphics to keep drawing surface state
|
|
Graphics2D gfx = (Graphics2D)g.create();
|
|
|
|
Part part = vertical ? Part.PP_BARVERT : Part.PP_BAR;
|
|
Part chunk = vertical ? Part.PP_CHUNKVERT : Part.PP_CHUNK;
|
|
|
|
// calculate the chunk offsets
|
|
int gap = xp.getInt(progressBar, Part.PP_PROGRESS, null,
|
|
Prop.PROGRESSSPACESIZE, 0);
|
|
int deltax = 0;
|
|
int deltay = 0;
|
|
if (!vertical) {
|
|
deltax = -box.width - gap;
|
|
deltay = 0;
|
|
} else {
|
|
deltax = 0;
|
|
deltay = -box.height - gap;
|
|
}
|
|
|
|
// Calculate the area of the chunks combined
|
|
Rectangle fullBox = getFullChunkBounds(box);
|
|
|
|
// save this box for the next time
|
|
previousFullBox = fullBox;
|
|
|
|
// this is the entire progress bar minus the track and borders
|
|
Insets ins = indeterminateInsets;
|
|
Rectangle progbarExtents = new Rectangle(ins.left, ins.top,
|
|
bgwidth - ins.left - ins.right,
|
|
bgheight - ins.top - ins.bottom);
|
|
|
|
// only paint where the chunks overlap with the progress bar drawing area
|
|
Rectangle repaintArea = progbarExtents.intersection(fullBox);
|
|
|
|
// adjust the cliprect to chop the chunks when they go off the end
|
|
gfx.clip(repaintArea);
|
|
|
|
// get the skin
|
|
XPStyle.Skin skin = xp.getSkin(progressBar, chunk);
|
|
|
|
// do the drawing
|
|
gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
|
|
skin.paintSkin(gfx, box.x, box.y, box.width, box.height, null);
|
|
box.translate(deltax, deltay);
|
|
gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
|
|
skin.paintSkin(gfx, box.x, box.y, box.width, box.height, null);
|
|
box.translate(deltax, deltay);
|
|
gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
|
|
skin.paintSkin(gfx, box.x, box.y, box.width, box.height, null);
|
|
|
|
// get rid of our clip and composite changes
|
|
gfx.dispose();
|
|
}
|
|
|
|
private void paintXPBackground(Graphics g, boolean vertical,
|
|
int barRectWidth, int barRectHeight) {
|
|
XPStyle xp = XPStyle.getXP();
|
|
if (xp == null) {
|
|
return;
|
|
}
|
|
Part part = vertical ? Part.PP_BARVERT : Part.PP_BAR;
|
|
Skin skin = xp.getSkin(progressBar, part);
|
|
|
|
// Paint background
|
|
skin.paintSkin(g, 0, 0, barRectWidth, barRectHeight, null);
|
|
}
|
|
}
|