FileDocCategorySizeDatePackage
PieceGraphView.javaAPI DocAzureus 3.0.3.414447Wed Jun 27 13:46:00 BST 2007com.aelitis.azureus.ui.swt.views

PieceGraphView

public class PieceGraphView extends org.gudy.azureus2.ui.swt.views.AbstractIView
author
TuxPaper
created
Apr 9, 2007

Fields Summary
private boolean
onePiecePerBlock
private int
BLOCK_FILLSIZE
private static final int
BLOCK_SPACING
private int
BLOCK_SIZE
private static final int
BLOCKCOLOR_HAVEALL
private static final int
BLOCKCOLOR_NOHAVE
private static final int
BLOCKCOLOR_UPLOADING
private static final int
BLOCKCOLOR_DOWNLOADING
private static final int
BLOCKCOLOR_NOAVAIL
private static final int
BLOCKCOLOR_HAVESOME
private Color[]
blockColors
private Canvas
canvas
private Image
img
private Image
imgHaveAll
private Image
imgNoHave
private org.gudy.azureus2.core3.download.DownloadManager
dlm
private Comparator
compFindPEPiece
private final com.aelitis.azureus.ui.swt.skin.SWTSkinProperties
properties
private double[]
squareCache
Constructors Summary
public PieceGraphView()


	  
		this.properties = SWTSkinFactory.getInstance().getSkinProperties();
	
Methods Summary
private voidbuildImage()

		if (canvas == null || canvas.isDisposed()) {
			return;
		}

		canvas.setBackground(ColorCache.getColor(canvas.getDisplay(), "#1b1b1b"));

		Rectangle bounds = canvas.getClientArea();
		if (bounds.isEmpty()) {
			return;
		}

		if (dlm == null) {
			canvas.redraw();
			return;
		}

		DiskManagerPiece[] dm_pieces = null;

		PEPeerManager pm = dlm.getPeerManager();

		DiskManager dm = dlm.getDiskManager();

		if (pm == null || dm == null) {
			canvas.redraw();
			return;
		}

		dm_pieces = dm.getPieces();

		if (dm_pieces == null || dm_pieces.length == 0) {
			canvas.redraw();
			return;
		}

		int numPieces = dm_pieces.length;

		if (imgHaveAll == null || imgHaveAll.isDisposed()) {
			imgHaveAll = new Image(canvas.getDisplay(), BLOCK_SIZE, BLOCK_SIZE);
			GC gc = new GC(imgHaveAll);
			try {
				try {
					gc.setAntialias(SWT.ON);
				} catch (Exception e) {
					// ignore
				}
				gc.setBackground(canvas.getBackground());
				gc.fillRectangle(imgHaveAll.getBounds());

				gc.setBackground(blockColors[BLOCKCOLOR_HAVEALL]);
				gc.fillRoundRectangle(1, 1, BLOCK_FILLSIZE, BLOCK_FILLSIZE,
						BLOCK_FILLSIZE, BLOCK_FILLSIZE);
			} finally {
				gc.dispose();
			}
		}

		if (imgNoHave == null || imgNoHave.isDisposed()) {
			imgNoHave = new Image(canvas.getDisplay(), BLOCK_SIZE, BLOCK_SIZE);
			GC gc = new GC(imgNoHave);
			try {
				try {
					gc.setAntialias(SWT.ON);
				} catch (Exception e) {
					// ignore
				}
				gc.setBackground(canvas.getBackground());
				gc.fillRectangle(imgNoHave.getBounds());

				gc.setBackground(blockColors[BLOCKCOLOR_NOHAVE]);
				gc.fillRoundRectangle(1, 1, BLOCK_FILLSIZE, BLOCK_FILLSIZE,
						BLOCK_FILLSIZE, BLOCK_FILLSIZE);
			} finally {
				gc.dispose();
			}
		}

		boolean clearImage = img == null || img.isDisposed()
				|| img.getBounds().width != bounds.width
				|| img.getBounds().height != bounds.height;
		if (clearImage) {
			if (img != null && !img.isDisposed()) {
				img.dispose();
			}
			System.out.println("clear " + img);
			img = new Image(canvas.getDisplay(), bounds.width, bounds.height);
			squareCache = null;
		}

		PEPiece[] currentDLPieces = dlm.getCurrentPieces();
		Arrays.sort(currentDLPieces, compFindPEPiece);

		// find upload pieces
		ArrayList currentULPieces = new ArrayList();
		ArrayList futureULPieces = new ArrayList();
		PEPeer[] peers = (PEPeer[]) pm.getPeers().toArray(new PEPeer[0]);
		for (int i = 0; i < peers.length; i++) {
			PEPeer peer = peers[i];
			int[] peerRequestedPieces = peer.getIncomingRequestedPieceNumbers();
			if (peerRequestedPieces != null && peerRequestedPieces.length > 0) {
				currentULPieces.add(new Long(peerRequestedPieces[0]));
				for (int j = 1; j < peerRequestedPieces.length; j++) {
					futureULPieces.add(new Long(peerRequestedPieces[j]));
				}
			}

			// we'll have duplicates
			Collections.sort(currentULPieces);
			Collections.sort(futureULPieces);
		}

		int iNumCols = bounds.width / BLOCK_SIZE;
		int iNumRows = bounds.height / BLOCK_SIZE;
		int numSquares = onePiecePerBlock ? numPieces : iNumCols * iNumRows;
		double numPiecesPerSquare = numPieces / (double) numSquares;
		//System.out.println("numPiecesPerSquare=" + numPiecesPerSquare);

		if (squareCache == null || squareCache.length != numSquares) {
			squareCache = new double[numSquares];
			Arrays.fill(squareCache, -1);
		}

		int[] availability = pm.getAvailability();
		
		int numRedraws = 0;

		GC gc = new GC(img);
		try {
			int iRow = 0;
			if (clearImage) {
				gc.setBackground(canvas.getBackground());
				gc.fillRectangle(bounds);
			}

			try {
				gc.setAntialias(SWT.ON);
				gc.setInterpolation(SWT.NONE);
			} catch (Exception e) {
				// ignore
			}
			int iCol = 0;
			for (int squareNo = 0; squareNo < numSquares; squareNo++) {
				if (iCol >= iNumCols) {
					iCol = 0;
					iRow++;
				}

				int startNo = (int) (squareNo * numPiecesPerSquare);
				int count = (int) ((squareNo + 1) * numPiecesPerSquare) - startNo;
				if (count == 0) {
					count = 1;
				}
				//if (count > 1) System.out.println("!!! " + startNo);

				//System.out.println(startNo + ";" + count);

				double pctDone = getPercentDone(startNo, count, dm_pieces);
				//System.out.print(pctDone + ";");

				int colorIndex;
				int iXPos = iCol * BLOCK_SIZE;
				int iYPos = iRow * BLOCK_SIZE;

				if (pctDone == 1) {
					if (squareCache[squareNo] != pctDone) {
						squareCache[squareNo] = pctDone;
						gc.drawImage(imgHaveAll, iXPos, iYPos);
						if (!clearImage) {
							numRedraws++;
							canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
						}
					}
				} else if (pctDone == 0) {
					if (squareCache[squareNo] != pctDone) {
						squareCache[squareNo] = pctDone;
						gc.drawImage(imgNoHave, iXPos, iYPos);
						if (!clearImage) {
							numRedraws++;
							canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
						}
					}
				} else {
					// !done
					boolean isDownloading = false;
					for (int i = startNo; i < startNo + count; i++) {
						if (Arrays.binarySearch(currentDLPieces, new Long(i),
								compFindPEPiece) >= 0) {
							isDownloading = true;
							break;
						}
					}

					double val = pctDone + (isDownloading ? 0 : 1);
					if (squareCache[squareNo] != val) {
						squareCache[squareNo] = val;
						gc.drawImage(imgNoHave, iXPos, iYPos);

						int size = (int) (BLOCK_FILLSIZE * pctDone);
						if (size == 0) {
							size = 1;
						}
						int q = (int) ((BLOCK_FILLSIZE - size) / 2.0 + 0.5) + 1;

						colorIndex = isDownloading ? BLOCKCOLOR_DOWNLOADING
								: BLOCKCOLOR_HAVESOME;
						gc.setBackground(blockColors[colorIndex]);
						gc.fillOval(iXPos + q, iYPos + q, size, size);
						//gc.fillRoundRectangle(iXPos + q, iYPos + q, size, size, size, size);
						if (!clearImage) {
							numRedraws++;
							canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
						}
					}
				}

				for (int i = startNo; i < startNo + count; i++) {
					if (Collections.binarySearch(currentULPieces, new Long(i)) >= 0) {
						colorIndex = BLOCKCOLOR_UPLOADING;
						int size = BLOCK_FILLSIZE + 1;

						gc.setForeground(blockColors[colorIndex]);
						gc.drawRoundRectangle(iXPos, iYPos, size, size, size, size);
						if (!clearImage) {
							numRedraws++;
							canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
						}
						squareCache[squareNo] = -1;
						break;
					} else if (Collections.binarySearch(futureULPieces, new Long(i)) >= 0) {
						colorIndex = BLOCKCOLOR_UPLOADING;
						int size = BLOCK_FILLSIZE + 1;

						gc.setForeground(blockColors[colorIndex]);
						gc.setLineStyle(SWT.LINE_DOT);
						gc.drawRoundRectangle(iXPos, iYPos, size, size, size, size);
						if (!clearImage) {
							numRedraws++;
							canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
						}
						gc.setLineStyle(SWT.LINE_SOLID);
						squareCache[squareNo] = -1;
						break;
					}
				}

				if (availability != null) {
					boolean hasNoAvail = false;
					for (int i = startNo; i < startNo + count; i++) {
						if (availability[i] == 0) {
							hasNoAvail = true;
							squareCache[squareNo] = -1;
							break;
						}
					}

					if (hasNoAvail) {
						gc.setForeground(blockColors[BLOCKCOLOR_NOAVAIL]);
						gc.drawRectangle(iXPos, iYPos, BLOCK_FILLSIZE + 1,
								BLOCK_FILLSIZE + 1);
						if (!clearImage) {
							numRedraws++;
							canvas.redraw(iXPos, iYPos, BLOCK_SIZE, BLOCK_SIZE, false);
						}
					}
				}

				iCol++;
			}
			//System.out.println("redraws " + numRedraws);
		} catch (Exception e) {
			Debug.out(e);
		} finally {
			gc.dispose();
		}

		//canvas.redraw();
	
private voidcalcBlockSize()

		if (!onePiecePerBlock) {
			buildImage();
			return;
		}
		Utils.execSWTThread(new AERunnable() {
			public void runSupport() {
				TOTorrent torrent = dlm == null ? null : dlm.getTorrent();
				if (torrent == null) {
					BLOCK_SIZE = 21 + BLOCK_SPACING;
				} else {
					long numPieces = torrent.getNumberOfPieces();
					Rectangle bounds = canvas.getClientArea();
					BLOCK_SIZE = (int) Math.sqrt((double) (bounds.width * bounds.height)
							/ numPieces);
					if (BLOCK_SIZE <= 0) {
						BLOCK_SIZE = 1;
					}
					// since calc above doesn't account for not splitting squares accross
					// rows, make sure we can fit.  If we can't, we have to shrink
					int numCanFit = (bounds.width / BLOCK_SIZE)
							* (bounds.height / BLOCK_SIZE);
					if (numCanFit < numPieces) {
						BLOCK_SIZE--;
					}
					//System.out.println((float)(bounds.width * bounds.height) / numPieces);
					//System.out.println(BLOCK_SIZE + ";" + (bounds.width / BLOCK_SIZE));

					if (BLOCK_SIZE < 2) {
						BLOCK_SIZE = 2;
					}
				}

				BLOCK_FILLSIZE = BLOCK_SIZE - BLOCK_SPACING;

				Utils.disposeSWTObjects(new Object[] {
					imgHaveAll,
					imgNoHave
				});

				buildImage();
			}
		});
	
public voiddataSourceChanged(java.lang.Object newDataSource)

		if (newDataSource instanceof DownloadManager) {
			dlm = (DownloadManager) newDataSource;
		} else {
			dlm = null;
		}
		calcBlockSize();
	
public CompositegetComposite()

		return canvas;
	
private doublegetPercentDone(int startNo, int count, org.gudy.azureus2.core3.disk.DiskManagerPiece[] dm_pieces)

param
startNo
param
count
param
dm_pieces
return
since
3.0.1.1


		int totalComplete = 0;
		int totalBlocks = 0;
		for (int i = startNo; i < startNo + count; i++) {
			DiskManagerPiece piece = dm_pieces == null ? null : dm_pieces[i];
			int numBlocks = piece.getNbBlocks();
			totalBlocks += numBlocks;

			boolean done = (piece == null) ? false : piece.isDone();

			if (done) {
				totalComplete += numBlocks;
			} else {
				// !done
				totalComplete += piece.getNbWritten();
			}
		}
		return (double) totalComplete / totalBlocks;
	
public voidinitialize(Composite parent)


		blockColors = new Color[] {
			properties.getColor("color.pieceview.alldone"),
			properties.getColor("color.pieceview.notdone"),
			properties.getColor("color.pieceview.uploading"),
			properties.getColor("color.pieceview.downloading"),
			properties.getColor("color.pieceview.noavail"),
			properties.getColor("color.pieceview.havesome"),
		};

		compFindPEPiece = new Comparator() {
			public int compare(Object arg0, Object arg1) {
				int arg0no = (arg0 instanceof PEPiece)
						? ((PEPiece) arg0).getPieceNumber() : ((Long) arg0).intValue();
				int arg1no = (arg1 instanceof PEPiece)
						? ((PEPiece) arg1).getPieceNumber() : ((Long) arg1).intValue();
				return arg0no - arg1no;
			}
		};

		canvas = new Canvas(parent, SWT.NO_BACKGROUND);
		canvas.setLayout(new FillLayout());

		canvas.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				if (img != null && !img.isDisposed()) {
					Rectangle bounds = img.getBounds();
					if (bounds.width >= e.width && bounds.height >= e.height) {
						e.gc.drawImage(img, e.x, e.y, e.width, e.height, e.x, e.y, e.width,
								e.height);
					}
				} else {
					e.gc.fillRectangle(e.x, e.y, e.width, e.height);
				}
			}
		});

		canvas.addListener(SWT.Resize, new Listener() {
			public void handleEvent(Event event) {
				calcBlockSize();
			}
		});
	
public voidrefresh()

		buildImage();