package gui.controls; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; 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.openslx.thrifthelper.TransferStatusWrapper; public class BlockProgressBar extends Canvas { private final Color white, blue, black; private final Color[] blockColors = new Color[5]; private final TransferStatusWrapper blocks = new TransferStatusWrapper(null); private boolean simpleMode = true; public BlockProgressBar(Composite parent) { super(parent, SWT.NO_BACKGROUND); setupListeners(); white = getDisplay().getSystemColor(SWT.COLOR_WHITE); blue = getDisplay().getSystemColor(SWT.COLOR_BLUE); black = getDisplay().getSystemColor(SWT.COLOR_BLACK); // 0 = complete, 1 = missing, 2 = uploading, 3 = queued for copying, 4 = copying blockColors[0] = black; blockColors[1] = getDisplay().getSystemColor(SWT.COLOR_RED); blockColors[2] = getDisplay().getSystemColor(SWT.COLOR_YELLOW); blockColors[3] = blue; blockColors[4] = getDisplay().getSystemColor(SWT.COLOR_GREEN); } public void setStatus(byte[] blocks) { this.blocks.setBlocks(blocks); this.redraw(); } private void setupListeners() { final BlockProgressBar me = this; // Paint listener this.addPaintListener(new PaintListener() { @Override public void paintControl(PaintEvent e) { me.draw(e); } }); this.addMouseListener(new MouseListener() { @Override public void mouseUp(MouseEvent e) { } @Override public void mouseDown(MouseEvent e) { } @Override public void mouseDoubleClick(MouseEvent e) { me.toggleMode(); } }); } private void toggleMode() { simpleMode = !simpleMode; this.redraw(); } private void draw(PaintEvent e) { if (blocks.isEmpty()) { // No valid block data, draw white window e.gc.setBackground(white); e.gc.fillRectangle(e.x, e.y, e.width, e.height); } else if (simpleMode) { drawSimple(e); } else { drawDetailed(e); } } private void drawSimple(PaintEvent e) { final Rectangle a = this.getClientArea(); final float width = a.width - 2; final float complete = blocks.getComplete(); final float doneWidth = width * complete; e.gc.setBackground(blue); e.gc.fillRectangle(a.x, a.y, (int) doneWidth, a.height); e.gc.setBackground(white); e.gc.fillRectangle(a.x + (int) doneWidth, a.y, (int) (width - doneWidth), a.height); final String progress = (int) (complete * 100) + "%"; Point textExtent = e.gc.textExtent(progress, SWT.DRAW_TRANSPARENT); final int textX = a.x + (a.width - textExtent.x) / 2; final int textY = a.y + (a.height - textExtent.y) / 2; e.gc.setForeground(white); e.gc.drawText(progress, textX - 1, textY - 1, true); e.gc.drawText(progress, textX + 1, textY + 1, true); e.gc.setForeground(black); e.gc.drawText(progress, textX, textY, true); } private void drawDetailed(PaintEvent e) { final int blockCount = blocks.getBlockCount(); // Calculate display mode final Rectangle a = this.getClientArea(); final float width = a.width - 2; float blockWidth = width / blockCount; int rows = 1; while (blockWidth * rows < 6 && a.height / rows > 8) { rows++; } blockWidth *= rows; final float blockHeight; final float blockHeightVisible; if (rows == 1) { blockHeightVisible = blockHeight = a.height; } else { blockHeight = (a.height + 2) / rows; blockHeightVisible = blockHeight - 2; } // Draw float x = a.x, y = a.y; for (byte block : blocks.getBlocks()) { if (block >= 0 && block < blockColors.length) { e.gc.setBackground(blockColors[block]); } else { e.gc.setBackground(white); } e.gc.fillRectangle((int) x, (int) y, (int) (x + blockWidth) - (int) x, (int) (y + blockHeightVisible) - (int) y); x += blockWidth; if (x + 0.5 > a.width) { e.gc.setBackground(white); e.gc.fillRectangle(a.x, (int) (y + blockHeightVisible), a.width, 2); x = a.x; y += blockHeight; } } // If we're multiline and have an odd number of blocks, there might be some remaining space - draw white if (x + 0.5 < a.width) { e.gc.setBackground(white); e.gc.fillRectangle((int) x, (int) y, (int) (x + blockWidth) - (int) x, (int) (y + blockHeightVisible) - (int) y); } } }