JUnitProgressBar.java
package com.codeaffine.extras.jdt.internal.junitstatus;
import java.util.Objects;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import com.codeaffine.extras.jdt.internal.junitstatus.TextAnimation.TextAnimationPainter;
public class JUnitProgressBar extends Canvas implements TextAnimationPainter {
private static final int ARC_SIZE = 3;
private static final int DEFAULT_WIDTH = 160;
private static final int DEFAULT_HEIGHT = 18;
private final TextAnimation textAnimation;
private String text;
private int textAlignment;
private int maximum;
private int selection;
private Color barColor;
public JUnitProgressBar( Composite parent ) {
super( parent, SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED | SWT.NO_FOCUS );
text = "";
textAlignment = SWT.LEFT;
textAnimation = new TextAnimation( this, this );
registerListeners();
}
public void setValues( String text, int textAlignment, Color barColor, int selection, int maximum ) {
if( valuesChanged( text, textAlignment, barColor, selection, maximum ) ) {
this.text = text;
this.textAnimation.setText( text );
this.textAlignment = textAlignment;
this.barColor = barColor;
this.selection = selection;
this.maximum = maximum;
redraw();
}
}
public void setMaximum( int maximum ) {
setValues( text, textAlignment, barColor, selection, maximum );
}
public int getMaximum() {
return maximum;
}
public void setSelection( int selection ) {
setValues( text, textAlignment, barColor, selection, maximum );
}
public int getSelection() {
return selection;
}
public void setBarColor( Color barColor ) {
setValues( text, textAlignment, barColor, selection, maximum );
}
public Color getBarColor() {
return barColor;
}
public void setText( String text ) {
setValues( text, textAlignment, barColor, selection, maximum );
}
public String getText() {
return text;
}
public void setTextAlignment( int textAlignment ) {
setValues( text, textAlignment, barColor, selection, maximum );
}
public int getTextAlignment() {
return textAlignment;
}
@Override
public void drawText( TextAnimation textAnimation ) {
redraw();
}
@Override
public Point computeSize( int wHint, int hHint, boolean changed ) {
checkWidget();
Point result = new Point( DEFAULT_WIDTH, DEFAULT_HEIGHT );
if( wHint != SWT.DEFAULT ) {
result.x = wHint;
}
if( hHint != SWT.DEFAULT ) {
result.y = hHint;
}
return result;
}
private void registerListeners() {
addListener( SWT.Resize, event -> redraw() );
addListener( SWT.Paint, event -> paint( event.gc ) );
}
private void paint( GC gc ) {
int style = ( maximum > 0 ? SWT.BORDER : SWT.NONE ) | textAlignment;
String text = textAnimation.getAnimatedText();
new Painter( gc, getClientArea(), text, barColor, getBarWidth(), style ).paint();
}
int getBarWidth() {
int result = selection;
Rectangle clientArea = getClientArea();
if( maximum > 0 ) {
if( clientArea.width != 0 ) {
result = Math.max( 0, selection * ( clientArea.width - 2 ) / maximum );
}
} else {
result = 0;
}
return Math.min( clientArea.width - 2, result );
}
private boolean valuesChanged( String text, int textAlignment, Color barColor, int selection, int maximum ) {
return !Objects.equals( this.text, text )
|| this.textAlignment != textAlignment
|| !Objects.equals( this.barColor, barColor )
|| this.selection != selection
|| this.maximum != maximum;
}
private static class Painter {
private final GC gc;
private final Rectangle clientArea;
private final String text;
private final Color barColor;
private final int barWidth;
private final int style;
Painter( GC gc, Rectangle clientArea, String text, Color barColor, int barWidth, int style ) {
this.gc = gc;
this.clientArea = clientArea;
this.text = text;
this.barColor = barColor;
this.barWidth = barWidth;
this.style = style;
}
void paint() {
prepareGC();
drawBorder();
drawBar();
drawText();
}
private void prepareGC() {
if( gc.getAdvanced() ) {
gc.setTextAntialias( SWT.ON );
}
gc.fillRectangle( clientArea );
}
private void drawBorder() {
if( ( style & SWT.BORDER ) != 0 ) {
int x = clientArea.x;
int y = clientArea.y;
int width = clientArea.width - 1;
int height = clientArea.height - 1 - 1;
gc.setAlpha( 255 );
gc.setForeground( getSystemColor( SWT.COLOR_WIDGET_NORMAL_SHADOW ) );
gc.drawRoundRectangle( x, y, width, height, ARC_SIZE, ARC_SIZE );
}
}
private void drawBar() {
if( barColor != null ) {
gc.setAlpha( 200 );
gc.setBackground( barColor );
gc.fillRoundRectangle( 1, 1, barWidth, clientArea.height - 2 - 1, ARC_SIZE, ARC_SIZE );
}
}
private void drawText() {
gc.setAlpha( 255 );
Rectangle rect = insideBorderArea();
Point textLocation = getTextLocation( rect );
Color defaultForeground = getSystemColor( SWT.COLOR_WIDGET_FOREGROUND );
drawText( textLocation, defaultForeground, null );
Color barForeground = getBarForegroundColor();
if( !equals( defaultForeground, barForeground ) ) {
Rectangle clipping = new Rectangle( rect.x, rect.y, barWidth, rect.height );
drawText( textLocation, barForeground, clipping );
}
}
private void drawText( Point location, Color foreground, Rectangle clipping ) {
Rectangle previousClipping = gc.getClipping();
if( clipping != null ) {
gc.setClipping( clipping );
}
gc.setForeground( foreground );
gc.drawText( text, location.x, location.y, SWT.DRAW_TRANSPARENT );
if( clipping != null ) {
gc.setClipping( previousClipping );
}
}
private Point getTextLocation( Rectangle clientArea ) {
Point textSize = gc.textExtent( text );
int x = 3;
if( ( style & SWT.CENTER ) != 0 ) {
x = ( clientArea.width - textSize.x ) / 2;
}
int y = ( clientArea.height - textSize.y ) / 2 + 1;
return new Point( x, y );
}
private Color getBarForegroundColor() {
Color result = getSystemColor( SWT.COLOR_WIDGET_FOREGROUND );
if( barColor != null ) {
int red = barColor.getRed();
int green = barColor.getGreen();
int blue = barColor.getBlue();
double y = ( 299 * red + 587 * green + 114 * blue ) / 1000;
result = y >= 128 ? getSystemColor( SWT.COLOR_BLACK ) : getSystemColor( SWT.COLOR_WHITE );
}
return result;
}
private Color getSystemColor( int id ) {
return gc.getDevice().getSystemColor( id );
}
private Rectangle insideBorderArea() {
return new Rectangle( clientArea.x + 1, clientArea.y + 1, clientArea.width - 2, clientArea.height - 2 );
}
private static boolean equals( Color color1, Color color2 ) {
return color1.getRGB().equals( color2.getRGB() );
}
}
}