/*******************************************************************************
* Copyright (c) 2011, 2012 Anton Gorenkov
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Anton Gorenkov - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.testsrunner.internal.ui.view;
import org.eclipse.cdt.testsrunner.model.ITestingSession;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
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 org.eclipse.swt.widgets.Display;
/**
* A progress bar with a red/green indication for testing success or failure.
*/
public class ProgressBar extends Canvas {
/** Default bar width */
private static final int DEFAULT_WIDTH = 160;
/** Default bar height */
private static final int DEFAULT_HEIGHT = 18;
/** Testing session to show progress bar for. */
private ITestingSession testingSession;
/** Current bar width. */
private int colorBarWidth;
/** The bar color when everything is OK (no tests failed and no testing errors). */
private Color okColor;
/** The bar color when there are tests failed and or testing errors. */
private Color failureColor;
/** The bar color when the testing session was stopped by user. */
private Color stoppedColor;
public ProgressBar(Composite parent, ITestingSession testingSession) {
super(parent, SWT.NONE);
addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
updateInfoFromSession();
}
});
addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
paint(e);
}
});
// Manage progress bar colors
Display display = parent.getDisplay();
failureColor = new Color(display, 159, 63, 63);
okColor = new Color(display, 95, 191, 95);
stoppedColor = new Color(display, 120, 120, 120);
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
failureColor.dispose();
okColor.dispose();
stoppedColor.dispose();
}
});
setTestingSession(testingSession);
}
/**
* Sets the testing session to show information about.
*
* @param testingSession testing session (null is not acceptable)
*/
public void setTestingSession(ITestingSession testingSession) {
this.testingSession = testingSession;
updateInfoFromSession();
}
/**
* Updates the progress from the currently set testing session.
*/
public void updateInfoFromSession() {
recalculateColorBarWidth();
redraw();
}
/**
* Sets the color of the progress bar depending on the testing session.
*
* @param gc gc
*/
private void setStatusColor(GC gc) {
if (testingSession.wasStopped())
gc.setBackground(stoppedColor);
else if (testingSession.hasErrors())
gc.setBackground(failureColor);
else
gc.setBackground(okColor);
}
/**
* Calculate the width of the progress rectangle in a widget.
*
* @note If total tests count is known it is used to determine width of the
* progress rectangle. If it isn't the width of progress rectangle is set to
* the half of a widget.
*/
private void recalculateColorBarWidth() {
Rectangle r = getClientArea();
int newColorBarWidth;
if (testingSession.getTotalCounter() > 0) {
newColorBarWidth = testingSession.getCurrentCounter()*(r.width-2)/testingSession.getTotalCounter();
} else {
newColorBarWidth = testingSession.getCurrentCounter() > 0 ? (r.width-2)/2 : (testingSession.isFinished() ? r.width-2 : 0);
}
colorBarWidth = Math.max(0, newColorBarWidth);
}
/**
* Draws the widget border
*/
private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) {
gc.setForeground(topleft);
gc.drawLine(x, y, x+w-1, y);
gc.drawLine(x, y, x, y+h-1);
gc.setForeground(bottomright);
gc.drawLine(x+w, y, x+w, y+h);
gc.drawLine(x, y+h, x+w, y+h);
}
/**
* Handles paint event and redraws the widget if necessary.
*
* @param event paint event
*/
private void paint(PaintEvent event) {
GC gc = event.gc;
Display disp = getDisplay();
Rectangle rect = getClientArea();
gc.fillRectangle(rect);
drawBevelRect(gc, rect.x, rect.y, rect.width-1, rect.height-1,
disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW),
disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
setStatusColor(gc);
colorBarWidth = Math.min(rect.width-2, colorBarWidth);
gc.fillRectangle(1, 1, colorBarWidth, rect.height-2);
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
checkWidget();
Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
if (wHint != SWT.DEFAULT) {
size.x = wHint;
}
if (hHint != SWT.DEFAULT) {
size.y = hHint;
}
return size;
}
}