/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.gui.look.ui;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicProgressBarUI;
import com.rapidminer.gui.look.Colors;
import com.rapidminer.gui.look.RapidLookAndFeel;
import com.rapidminer.gui.look.RapidLookTools;
/**
* The UI for progress bars.
*
* @author Marco Boeck
*/
public class ProgressBarUI extends BasicProgressBarUI {
/** the speed factor of the indeterminate animation */
private static final double ANIMATION_SPEED = 0.03;
/** the length of each individual part of the intermediate animation */
private static final int ANIMATION_BAR_LENGTH = 20;
public static ComponentUI createUI(JComponent x) {
return new ProgressBarUI();
}
@Override
protected void installDefaults() {
super.installDefaults();
}
@Override
protected int getBoxLength(int availableLength, int otherDimension) {
return availableLength;
}
@Override
protected void paintDeterminate(Graphics g, JComponent c) {
boolean compressed = Boolean.parseBoolean(String.valueOf(progressBar
.getClientProperty(RapidLookTools.PROPERTY_PROGRESSBAR_COMPRESSED)));
int y = 0;
int x = 0;
int w;
int h;
if (compressed) {
x = (int) (c.getWidth() * 0.67);
w = (int) (c.getWidth() * 0.33);
y = 3;
h = c.getHeight() - 6;
} else {
w = c.getWidth();
h = c.getHeight() / 2;
}
int amountFull = getAmountFull(progressBar.getInsets(), w, h);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (c.isOpaque()) {
if (c.getParent() != null) {
g2.setColor(c.getParent().getBackground());
} else {
g2.setColor(c.getBackground());
}
g2.fillRect(x, y, c.getWidth(), c.getHeight());
}
g2.setColor(Colors.PROGRESSBAR_BACKGROUND);
g2.fillRoundRect(x + 1, y + 1, w - 2, h - 2, RapidLookAndFeel.CORNER_DEFAULT_RADIUS,
RapidLookAndFeel.CORNER_DEFAULT_RADIUS);
g2.setColor(Colors.PROGRESSBAR_BORDER);
g2.drawRoundRect(x + 1, y + 1, w - 2, h - 2, RapidLookAndFeel.CORNER_DEFAULT_RADIUS,
RapidLookAndFeel.CORNER_DEFAULT_RADIUS);
Paint gp = new GradientPaint(x, y + 3, Colors.PROGRESSBAR_DETERMINATE_FOREGROUND_GRADIENT_START, x, h - 5,
Colors.PROGRESSBAR_DETERMINATE_FOREGROUND_GRADIENT_END);
g2.setPaint(gp);
g2.fillRoundRect(x + 3, y + 3, amountFull - 5, h - 5, RapidLookAndFeel.CORNER_DEFAULT_RADIUS / 2,
RapidLookAndFeel.CORNER_DEFAULT_RADIUS / 2);
drawString(g2, w, h, compressed);
}
@Override
protected void paintIndeterminate(Graphics g, JComponent c) {
boolean compressed = Boolean.parseBoolean(String.valueOf(progressBar
.getClientProperty(RapidLookTools.PROPERTY_PROGRESSBAR_COMPRESSED)));
int y = 0;
int x = 0;
int w;
int h;
if (compressed) {
x = (int) (c.getWidth() * 0.67);
w = (int) (c.getWidth() * 0.33);
y = 3;
h = c.getHeight() - 6;
} else {
w = c.getWidth();
h = c.getHeight() / 2;
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (c.isOpaque()) {
if (c.getParent() != null) {
g2.setColor(c.getParent().getBackground());
} else {
g2.setColor(c.getBackground());
}
g2.fillRect(x, y, c.getWidth(), c.getHeight());
}
g2.setColor(Colors.PROGRESSBAR_BACKGROUND);
g2.fillRoundRect(x + 1, y + 1, w - 2, h - 2, RapidLookAndFeel.CORNER_DEFAULT_RADIUS,
RapidLookAndFeel.CORNER_DEFAULT_RADIUS);
g2.setColor(Colors.PROGRESSBAR_BORDER);
g2.drawRoundRect(x + 1, y + 1, w - 2, h - 2, RapidLookAndFeel.CORNER_DEFAULT_RADIUS,
RapidLookAndFeel.CORNER_DEFAULT_RADIUS);
// make sure we don't draw over the boundaries
RoundRectangle2D clipRect = new RoundRectangle2D.Double(x + 3, y + 3, w - 5, h - 5,
RapidLookAndFeel.CORNER_DEFAULT_RADIUS / 2, RapidLookAndFeel.CORNER_DEFAULT_RADIUS / 2);
g2.setClip(clipRect);
for (double xCoord = x + -4 * ANIMATION_BAR_LENGTH + System.currentTimeMillis() * ANIMATION_SPEED
% (2 * ANIMATION_BAR_LENGTH); xCoord < x + w + 2 * ANIMATION_BAR_LENGTH;) {
g2.setColor(Colors.PROGRESSBAR_INDETERMINATE_FOREGROUND_1);
g2.fill(createIntermediateShape(xCoord, ANIMATION_BAR_LENGTH, h));
xCoord += ANIMATION_BAR_LENGTH;
g2.setColor(Colors.PROGRESSBAR_INDETERMINATE_FOREGROUND_2);
g2.fill(createIntermediateShape(xCoord, ANIMATION_BAR_LENGTH, h));
xCoord += ANIMATION_BAR_LENGTH;
}
g2.setClip(null);
drawString(g2, w, h, compressed);
}
private void drawString(Graphics2D g2, int w, int h, boolean compressed) {
if (progressBar.isStringPainted()) {
// need to reduce font size to fit available space.
// DO NOT CALL THIS EVERY TIME AS IT'S TREMENDOUSLY EXPENSIVE!!!
if (compressed && progressBar.getFont().getSize() != 11) {
progressBar.setFont(progressBar.getFont().deriveFont(11f));
}
FontMetrics fontSizer = progressBar.getFontMetrics(progressBar.getFont());
String displayString = progressBar.getString();
if (displayString == null || displayString.trim().isEmpty()) {
return;
}
int stringHeight = fontSizer.getHeight();
int stringWidth = fontSizer.stringWidth(displayString);
// if string is too wide, cut beginning off until it fits
while (stringWidth > w * 2) {
displayString = displayString.substring(0, (int) (displayString.length() * 0.9));
stringWidth = fontSizer.stringWidth(displayString);
}
g2.setColor(Colors.TEXT_FOREGROUND);
if (compressed) {
g2.drawString(displayString, (int) Math.max(0, w / 0.33 - w - stringWidth - 5), h - (h - stringHeight) / 2
- 1);
} else {
g2.drawString(displayString, w - stringWidth, h + stringHeight - 1);
}
}
}
/**
* Creates the shape for a single part of the intermediate bar.
*
* @param x
* @param width
* @param h
* @param verticval
* @return
*/
private Path2D createIntermediateShape(double x, double width, double h) {
int offset = 10;
Path2D path = new Path2D.Double();
path.append(new Line2D.Double(x, h, x + offset, 0), true);
path.append(new Line2D.Double(x + offset, 0, x + width + offset, 0), true);
path.append(new Line2D.Double(x + width + offset, 0, x + width, h), true);
path.append(new Line2D.Double(x + width, h, x, h), true);
return path;
}
}