package org.openslx.dozmod.gui.control; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.Rectangle2D; import javax.swing.JPanel; import org.openslx.thrifthelper.TransferStatusWrapper; @SuppressWarnings("serial") public class BlockProgressBar extends JPanel { private final Color[] blockColors = new Color[5]; private final TransferStatusWrapper blocks = new TransferStatusWrapper(null); private boolean simpleMode = true; public BlockProgressBar(byte[] blocks) { super(); setupListeners(); // 0 = complete, 1 = missing, 2 = uploading, 3 = queued for copying, 4 = copying blockColors[0] = Color.BLACK; blockColors[1] = Color.RED; blockColors[2] = Color.YELLOW; blockColors[3] = Color.BLUE; blockColors[4] = Color.GREEN; this.blocks.setBlocks(blocks); } public void setStatus(byte[] blocks) { this.blocks.setBlocks(blocks); this.repaint(100); } private void setupListeners() { final BlockProgressBar me = this; this.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { me.toggleMode(); } } }); } private void toggleMode() { simpleMode = !simpleMode; this.repaint(100); } @Override public void paintComponent(Graphics g) { if (blocks.isEmpty()) { // No valid block data, draw white window g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); } else if (simpleMode) { drawSimple(g); } else { drawDetailed(g); } } private void drawSimple(Graphics g) { final float width = getWidth(); final int height = getHeight(); final float complete = blocks.getComplete(); final float doneWidth = width * complete; final Rectangle doneRect = new Rectangle(0, 0, (int) doneWidth, height); final Rectangle remainingRect = new Rectangle((int) doneWidth, 0, (int) (width - doneWidth), height); g.setColor(Color.BLUE); g.fillRect(doneRect.x, doneRect.y, doneRect.width, doneRect.height); g.setColor(Color.WHITE); g.fillRect(remainingRect.x, remainingRect.y, remainingRect.width, remainingRect.height); final String progress = (int) (complete * 100) + "%"; Rectangle2D textExtent = g.getFontMetrics().getStringBounds(progress, g); final int textX = (int) ((width - textExtent.getWidth()) / 2); final int textY = (int) ((height - textExtent.getHeight()) / 2); g.setColor(Color.WHITE); g.setClip(doneRect.x, doneRect.y, doneRect.width, doneRect.height); g.drawString(progress, textX, textY); g.setColor(Color.BLACK); g.setClip(remainingRect.x, remainingRect.y, remainingRect.width, remainingRect.height); g.drawString(progress, textX, textY); } private void drawDetailed(Graphics g) { final int blockCount = blocks.getBlockCount(); // Calculate display mode final int height = getHeight(); final float width = getWidth() - 2; float blockWidth = width / blockCount; int rows = 1; while (blockWidth * rows < 6 && (float) height / rows > 7) { rows++; } blockWidth *= rows; final float blockHeight; final float blockHeightVisible; if (rows == 1) { blockHeightVisible = blockHeight = height; } else { blockHeight = (height + 2) / rows; blockHeightVisible = blockHeight - 2; } // Draw g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); float x = 0, y = 0; for (byte block : blocks.getBlocks()) { float toX = x + blockWidth; if (block >= 0 && block < blockColors.length) { g.setColor(blockColors[block]); final int boxWidth = ((int) toX) - ((int) x) - 1; final int boxHeight = (int) (y + blockHeightVisible) - (int) y; g.fillRect((int) x, (int) y, boxWidth > 1 ? boxWidth : 1, boxHeight > 1 ? boxHeight : 1); } x = toX; if (x + 0.5 > width) { x = 0; y += blockHeight; } } } }