package org.xtest.runner.statusbar;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
import org.xtest.runner.Activator;
import com.google.inject.Inject;
/**
* Status bar providing feedback to the user on the status of running Xtest tests.
*
* @author Michael Barry
*/
public class StatusBar extends WorkbenchWindowControlContribution implements
IStatusBarRepaintListener {
private Composite composite;
private final StatusBarController controller;
private final boolean enabled;
private final RGB green = new RGB(0x51, 0xa3, 0x51);
private Label label;
private Image progressBackground;
private final RGB red = new RGB(0xbd, 0x36, 0x2f);
@Inject
private StatusBar(StatusBarController controller) {
this.controller = controller;
controller.addListener(this);
enabled = Activator.getDefault().getPreferenceStore()
.getBoolean(Activator.SHOW_XTEST_RUNNER);
}
@Override
public void dispose() {
super.dispose();
controller.removeListener(this);
}
@Override
public void schedulePaint() {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
paint();
}
});
}
@Override
protected Control createControl(Composite parent) {
// create components and apply layout
composite = parent;
for (composite = parent; composite != null && !(composite instanceof ToolBar); composite = composite
.getParent()) {
}
if (composite == null) {
return parent;
}
if (enabled) {
composite.setBackgroundMode(SWT.INHERIT_DEFAULT);
composite.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event e) {
paint();
}
});
Composite composite = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().numColumns(1).margins(3, 3).applyTo(composite);
label = new Label(composite, SWT.BOLD);
label.setText("9999FFF/9999");
GridDataFactory.fillDefaults().grab(true, true).applyTo(label);
schedulePaint();
return composite;
} else {
// TODO Would be better to handle this through a visibleWhen clause in the extension,
// but that appears to not have any effect
// (https://bugs.eclipse.org/bugs/show_bug.cgi?id=201589)
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
composite.dispose();
dispose();
}
});
return new Label(parent, SWT.NONE);
}
}
private void paint() {
Image oldImage = progressBackground;
if (!composite.isDisposed()) {
Display display = composite.getDisplay();
Rectangle rect = composite.getClientArea();
boolean horizontal = rect.width > rect.height;
int boundWidth = rect.width;
int boundHeight = rect.height;
progressBackground = new Image(display, rect.width, rect.height);
GC gc = new GC(progressBackground);
try {
RGB rgb = controller.isPassing() ? green : red;
Color color = new Color(Display.getDefault(), rgb);
try {
Rectangle unknown;
Rectangle progress;
double completionRatio = controller.getCompletionRatio();
if (horizontal) {
boundWidth -= 1;
}
if (horizontal) {
int horizontalDivide = (int) (completionRatio * boundWidth);
int remainder = boundWidth - horizontalDivide;
unknown = new Rectangle(horizontalDivide, 0, remainder, boundHeight);
progress = new Rectangle(0, 0, horizontalDivide, boundHeight);
} else {
int verticalDivide = (int) (completionRatio * boundHeight);
int remainder = boundHeight - verticalDivide;
unknown = new Rectangle(0, 0, boundWidth, remainder);
progress = new Rectangle(0, remainder, boundWidth, verticalDivide);
}
gc.setBackground(color);
gc.fillRectangle(progress);
gc.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_GRAY));
gc.fillRectangle(unknown);
label.setText(controller.getText());
if (horizontal) {
gc.setBackground(Display.getDefault().getSystemColor(
SWT.COLOR_WIDGET_BACKGROUND));
gc.fillRectangle(boundWidth, 0, 4, boundHeight);
}
} finally {
color.dispose();
}
} finally {
gc.dispose();
}
composite.setBackgroundImage(progressBackground);
// If there was an old image, get rid of it now
if (oldImage != null) {
oldImage.dispose();
}
}
}
}