echopointng.progressbar.DefaultProgressBarRenderer Maven / Gradle / Ivy
Show all versions of ibis-echo2 Show documentation
package echopointng.progressbar;
/*
* This file is part of the Echo Point Project. This project is a collection
* of Components that have extended the Echo Web Application Framework.
*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*/
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import nextapp.echo2.app.AwtImageReference;
import nextapp.echo2.app.Border;
import nextapp.echo2.app.Component;
import nextapp.echo2.app.Extent;
import nextapp.echo2.app.ImageReference;
import nextapp.echo2.app.Style;
import echopointng.EPNG;
import echopointng.ProgressBar;
import echopointng.util.ColorKit;
import echopointng.util.FontKit;
/**
* The default ProgressBar renderer
*/
public class DefaultProgressBarRenderer implements ProgressBarRenderer, java.io.Serializable {
int borderSize = 0;
int height = 0;
int hspacer = 2;
private boolean isHorz;
ProgressBar pb = null;
int vspacer = 2;
int width = 0;
/**
* if we are HORZ then we draw from left to right and increase the x values
*
* if we are VERT, we draw from bottom to top and decrease the y values
*/
private void _drawBlocks(Graphics2D g, int numBlocks, int blockWidth, int blockHeight, int partialDraw, java.awt.Color clr) {
int x = 0 + hspacer + borderSize;
int y = 0 + vspacer + borderSize;
if (!_isHorz()) {
y = height - borderSize - blockHeight;
}
for (int i = 0; i < numBlocks; i++) {
g.setColor(clr);
//
// we adjust the paint block so that it leaves a gap on
// one side. 1 blockWidth includes this spacer.
int drawWidth = blockWidth;
int drawHeight = blockHeight;
int drawX = x;
int drawY = y;
if (_isHorz()) {
drawWidth -= hspacer;
//
// check if we are on the last block
if (i == numBlocks - 1 && partialDraw > 0) {
drawWidth = partialDraw;
}
x += blockWidth;
} else {
drawHeight -= vspacer;
//
// check if we are on the last block
if (i == numBlocks - 1 && partialDraw > 0) {
drawY = y + (drawHeight - partialDraw);
drawHeight = partialDraw;
}
y -= blockHeight;
}
g.fillRect(drawX, drawY, drawWidth, drawHeight);
}
}
/**
* Draw text center around the given height and width
*/
private void _drawText(Graphics2D g, float w, float h, String s, Color foreGround) {
if (s == null) {
return;
}
FontRenderContext frc = g.getFontRenderContext();
Font fnt = FontKit.makeAwtFont(_findFont(pb), new Font("Verdana", Font.BOLD, 12));
g.setColor(foreGround);
g.setFont(fnt);
TextLayout tl = new TextLayout(s, fnt, frc);
Rectangle rect = tl.getBounds().getBounds();
//float x = (width - (float) rect.getWidth()) / 2;
float y = (height - (float) rect.getHeight()) / 2;
y = y + (float) rect.getHeight();
int rotateDegress = 0;
// draw it horizntally if we can cause its easier to read
if (_isHorz() || rect.getWidth() < width) {
rotateDegress = 0;
} else {
rotateDegress = 90;
}
float fx = w / 2; // << -- my points of interest
float fy = h / 2; // << -- my points of interest
// text is draw from the base line so adjust to its
// logical bounding box, whcih is what we want centered
float x1 = fx - (rect.width / 2);
float y1 = fy + (rect.height / 2) - tl.getDescent();
// save the current transform
AffineTransform atPrev = g.getTransform();
// and make a new one around of point of interest
AffineTransform at = new AffineTransform();
at.setToIdentity();
at.rotate(Math.toRadians(rotateDegress), fx, fy);
at.translate(x1, y1);
g.setTransform(at);
tl.draw(g, 0, 0);
// debug - this draws a box around the text
// helps with visualising centering
//g.setColor(Color.black);
//g.draw(rect);
g.setTransform(atPrev);
}
/**
* Loops round and finds a font
*/
private nextapp.echo2.app.Font _findFont(Component c) {
nextapp.echo2.app.Font fnt = c.getFont();
while (c != null && fnt == null) {
c = c.getParent();
if (c != null)
fnt = c.getFont();
}
return fnt;
}
/**
* returns true if we are a HORIZONTAL PB
*/
private boolean _isHorz() {
return isHorz;
}
/**
* This method can be used by subclasses to customise how the
* ProgressBar
is to be displayed.
*
* The subclass must take into account the properties of the ProgressBar at
* the time the image is to be drawn. For example the orientation, the
* progress string etc...
*
* The default implementation create a AwtImageReference for display on the
* client via AWT graphics calls.
*
*/
public ImageReference drawProgressBar(ProgressBar progressBar) {
Style fallbackStyle = EPNG.getFallBackStyle(progressBar);
pb = progressBar;
Integer intObj = (Integer) getRP(pb, ProgressBar.PROPERTY_ORIENTATION, fallbackStyle);
isHorz = ProgressBar.ORIENTATION_HORIZONTAL == (intObj == null ? ProgressBar.ORIENTATION_HORIZONTAL : intObj.intValue());
intObj = (Integer) getRP(pb, ProgressBar.PROPERTY_NUMBER_OF_BLOCKS, fallbackStyle);
int TOTAL_NUM_BLOCKS = (intObj == null ? 10 : intObj.intValue());
Border border = (Border) getRP(pb, ProgressBar.PROPERTY_BORDER, fallbackStyle);
nextapp.echo2.app.Color borderColor = (border == null ? null : border.getColor());
java.awt.Color clrBorder = ColorKit.makeAwtColor(borderColor, Color.black);
java.awt.Color clrBackground = ColorKit.makeAwtColor(getRPColor(pb, ProgressBar.PROPERTY_BACKGROUND, fallbackStyle), Color.white);
java.awt.Color clrForeGround = ColorKit.makeAwtColor(getRPColor(pb, ProgressBar.PROPERTY_FOREGROUND, fallbackStyle), Color.black);
java.awt.Color clrCompleted = ColorKit.makeAwtColor(getRPColor(pb, ProgressBar.PROPERTY_COMPLETED_COLOR, fallbackStyle), Color.orange);
java.awt.Color clrUncompleted = ColorKit.makeAwtColor(getRPColor(pb, ProgressBar.PROPERTY_UNCOMPLETED_COLOR, fallbackStyle), Color.lightGray);
hspacer = 2;
vspacer = 2;
if (border != null && border.getSize() != null) {
borderSize = border.getSize().getValue();
} else {
borderSize = 0;
}
borderSize = 0;
Extent widthExt = (Extent) getRP(pb, ProgressBar.PROPERTY_WIDTH, fallbackStyle);
if (widthExt != null) {
width = widthExt.getValue();
} else {
width = 146;
}
Extent heightExt = (Extent) getRP(pb, ProgressBar.PROPERTY_HEIGHT, fallbackStyle);
if (heightExt != null) {
height = heightExt.getValue();
} else {
height = 30;
}
//
// the total width/height must divisible by TOTAL_NUM_BLOCKS
// otherwize will have pixels at the end left over just hanging there
//
int blockHeight = 0;
int blockWidth = 0;
int leftOver = 0;
if (_isHorz()) {
int innerWidth = width - (hspacer * 1) - (borderSize * 2);
int innerHeight = height - (vspacer * 2) - (borderSize * 2);
blockHeight = innerHeight;
blockWidth = innerWidth / TOTAL_NUM_BLOCKS;
leftOver = innerWidth - (blockWidth * TOTAL_NUM_BLOCKS);
if (leftOver > 0) {
width -= leftOver;
leftOver = 0;
}
} else {
int innerWidth = width - (hspacer * 2) - (borderSize * 2);
int innerHeight = height - (vspacer * 1) - (borderSize * 2);
blockWidth = innerWidth;
blockHeight = innerHeight / TOTAL_NUM_BLOCKS;
leftOver = innerHeight - (blockHeight * TOTAL_NUM_BLOCKS);
if (leftOver > 0) {
height -= leftOver;
leftOver = 0;
}
}
//
// create our Image
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
if (borderSize > 0) {
g.setColor(clrBorder);
g.fillRect(0, 0, width, height);
g.setColor(java.awt.Color.white);
g.fillRect(borderSize, borderSize, width - (borderSize * 2), height - (borderSize * 2));
} else {
g.setColor(clrBackground);
g.fillRect(0, 0, width, height);
}
////////////////////////////////
// draw each inactive block
_drawBlocks(g, TOTAL_NUM_BLOCKS, blockWidth, blockHeight, 0, clrUncompleted);
////////////////////////////////
// draw each active block up to the percent done
// and no more. No need to draw if its is zero percent!
//
int partialDraw = 0;
double pcDoneOrig = 100 * pb.getPercentComplete();
double pcDone = Math.round(pcDoneOrig);
pcDone = pcDone / 100;
if (pcDone > 0) {
double numBlocks = TOTAL_NUM_BLOCKS * pcDone;
double rem = numBlocks - Math.floor(numBlocks);
if (rem > 0) {
numBlocks += 1;
if (_isHorz())
partialDraw = (int) (rem * (blockWidth - hspacer));
else
partialDraw = (int) (rem * (blockHeight - vspacer));
}
_drawBlocks(g, (int) Math.floor(numBlocks), blockWidth, blockHeight, partialDraw, clrCompleted);
}
boolean isPainted = Boolean.TRUE.equals(getRP(pb,ProgressBar.PROPERTY_PROGRESS_STRING_PAINTED,fallbackStyle));
if (isPainted) {
String text = (String) getRP(pb,ProgressBar.PROPERTY_PROGRESS_STRING_PAINTED,fallbackStyle);
_drawText(g, width, height, text, clrForeGround);
}
g.dispose();
return new AwtImageReference(image);
}
private Object getRP(Component c, String propertyName, Style fallbackStyle) {
Object value = c.getRenderProperty(propertyName);
if (value == null && fallbackStyle != null) {
value = fallbackStyle.getProperty(propertyName);
}
return value;
}
private nextapp.echo2.app.Color getRPColor(Component c, String propertyName, Style fallbackStyle) {
Object value = c.getRenderProperty(propertyName);
if (value == null && fallbackStyle != null) {
value = fallbackStyle.getProperty(propertyName);
}
return (nextapp.echo2.app.Color) value;
}
/**
* A toString method for debugging
*/
public String toString() {
return "w=" + width + " h=" + height + " hs=" + hspacer + " vs=" + vspacer + " bs=" + borderSize;
}
}