summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/gui/control/BlockProgressBar.java
blob: c7e0172f7a55fa4da283878040e0d69754d7a5c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package org.openslx.dozmod.gui.control;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.JPanel;

import org.openslx.dozmod.filetransfer.TransferEvent;
import org.openslx.dozmod.gui.Gui;
import org.openslx.thrifthelper.TransferStatusWrapper;

public class BlockProgressBar extends JPanel {

	/**
	 * Version for serialization.
	 */
	private static final long serialVersionUID = 3530794778387334915L;

	private final Color[] blockColors = new Color[6];
	
	private static final Color potentialCompleteColor = new Color(215, 230, 255, 255);

	private final TransferStatusWrapper blocks = new TransferStatusWrapper(null);
	
	private final TransferStatusWrapper.Progress progress = new TransferStatusWrapper.Progress();

	private boolean simpleMode = true;

	private boolean showEstimatedComplete = false;
	
	private int locallyHashedBlockCount;

	public BlockProgressBar(byte[] blocks) {
		super();
		setPreferredSize(Gui.getScaledDimension(100, 32));
		setupListeners();
		// 0 = complete, 1 = missing, 2 = uploading, 3 = queued for copying, 4 = copying, 5 = hashing
		blockColors[0] = Color.BLACK;
		blockColors[1] = Color.RED;
		blockColors[2] = Color.YELLOW;
		blockColors[3] = Color.BLUE;
		blockColors[4] = Color.GREEN;
		blockColors[5] = Color.YELLOW.darker();
		this.blocks.setBlocks(blocks);
	}

	public void setStatus(TransferEvent event) {
		this.blocks.setBlocks(event.progress);
		this.locallyHashedBlockCount = event.locallyHashedCount;
		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) {
		if (g instanceof Graphics2D) {
			((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
					RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		}
		final int width = getWidth();
		final int height = getHeight();
		blocks.getCompleteEx(progress);
		final int doneWidth = (int) ((float) width * progress.done);
		final int potentialWidth = (int) ((float) width * progress.potentiallyDone);
		int sumWidth = doneWidth;
		g.setColor(Color.BLUE);
		g.fillRect(0, 0, doneWidth, height);
		if (showEstimatedComplete) {
			g.setColor(potentialCompleteColor);
			g.fillRect(doneWidth, 0, potentialWidth, height);
			sumWidth += potentialWidth;
		}
		g.setColor(Color.WHITE);
		g.fillRect(sumWidth, 0, width - sumWidth, height);
		final String percentDisplay = (int) (progress.done * 100) + "%";
		Rectangle2D textExtent = g.getFontMetrics().getStringBounds(percentDisplay, g);
		final double tw = textExtent.getWidth();
		final int textX = (int) ((width - tw) / 2);
		final int textXEnd = (int) ((width + tw) / 2);
		final int textY = (int) ((height + textExtent.getHeight()) / 2);
		if (doneWidth >= textX) {
			g.setColor(Color.WHITE);
			g.setClip(0, 0, doneWidth, height);
			g.drawString(percentDisplay, textX, textY);
		}
		if (doneWidth <= textXEnd) {
			g.setColor(Color.BLACK);
			g.setClip(doneWidth, 0, width - doneWidth, height);
			g.drawString(percentDisplay, 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;
		byte[] ba = blocks.getBlocks();
		for (int i = 0; i < ba.length; ++i) {
			byte block = ba[i];
			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;
				if (i < locallyHashedBlockCount) {
					g.fillRect((int) x, (int) y, boxWidth > 1 ? boxWidth : 1, boxHeight > 1 ? boxHeight : 1);
				} else {
					g.drawRect((int) x, (int) y, boxWidth > 1 ? boxWidth : 1, boxHeight > 1 ? boxHeight : 1);
				}
			}
			x = toX;
			if (x + 0.5 > width) {
				x = 0;
				y += blockHeight;
			}
		}
	}

	public void showOptimisticComplete(boolean b) {
		this.showEstimatedComplete  = b;
	}

}