FileDocCategorySizeDatePackage
PieceInfoView.javaAPI DocAzureus 3.0.3.418117Wed May 09 17:40:32 BST 2007org.gudy.azureus2.ui.swt.views.piece

PieceInfoView

public class PieceInfoView extends org.gudy.azureus2.ui.swt.views.AbstractIView implements org.gudy.azureus2.core3.download.DownloadManagerPeerListener, org.gudy.azureus2.ui.swt.debug.ObfusticateImage
author
TuxPaper
created
Feb 26, 2007

Fields Summary
private static final int
BLOCK_FILLSIZE
private static final int
BLOCK_SPACING
private static final int
BLOCK_SIZE
private static final int
BLOCKCOLOR_HAVE
private static final int
BLOCKCOLORL_NOHAVE
private static final int
BLOCKCOLOR_TRANSFER
private static final int
BLOCKCOLOR_NEXT
private static final int
BLOCKCOLOR_AVAILCOUNT
private Composite
pieceInfoComposite
private org.eclipse.swt.custom.ScrolledComposite
sc
protected Canvas
pieceInfoCanvas
private Color[]
blockColors
private Label
topLabel
private Label
imageLabel
private int
graphicsUpdate
private int
loopFactor
private Font
font
Image
img
private Comparator
compFindPEPiece
private org.gudy.azureus2.core3.download.DownloadManager
dlm
private boolean
alreadyFilling
Constructors Summary
public PieceInfoView()
Initialize


	 	 
	  
		blockColors = new Color[] {
			Colors.blues[Colors.BLUES_DARKEST],
			Colors.white,
			Colors.red,
			Colors.fadedRed,
			Colors.black
		};

		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 arg1no - arg0no;
			}
		};
	
Methods Summary
private CompositecreatePeerInfoPanel(Composite parent)

		GridLayout layout;
		GridData gridData;

		// Peer Info section contains
		// - Peer's Block display
		// - Peer's Datarate
		pieceInfoComposite = new Composite(parent, SWT.NONE);
		layout = new GridLayout();
		layout.numColumns = 2;
		layout.horizontalSpacing = 0;
		layout.verticalSpacing = 0;
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		pieceInfoComposite.setLayout(layout);
		gridData = new GridData(GridData.FILL, GridData.FILL, true, true);
		pieceInfoComposite.setLayoutData(gridData);

		imageLabel = new Label(pieceInfoComposite, SWT.NULL);
		gridData = new GridData();
		imageLabel.setLayoutData(gridData);

		topLabel = new Label(pieceInfoComposite, SWT.NULL);
		gridData = new GridData(SWT.FILL, SWT.DEFAULT, false, false);
		topLabel.setLayoutData(gridData);

		sc = new ScrolledComposite(pieceInfoComposite, SWT.V_SCROLL);
		sc.setExpandHorizontal(true);
		sc.setExpandVertical(true);
		layout = new GridLayout();
		layout.horizontalSpacing = 0;
		layout.verticalSpacing = 0;
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		sc.setLayout(layout);
		gridData = new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1);
		sc.setLayoutData(gridData);
		sc.getVerticalBar().setIncrement(BLOCK_SIZE);

		pieceInfoCanvas = new Canvas(sc, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
		gridData = new GridData(GridData.FILL, SWT.DEFAULT, true, false);
		pieceInfoCanvas.setLayoutData(gridData);
		pieceInfoCanvas.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				if (e.width <= 0 || e.height <= 0)
					return;
				try {
					Rectangle bounds = (img == null) ? null : img.getBounds();
					if (bounds == null) {
						e.gc.fillRectangle(e.x, e.y, e.width, e.height);
					} else {
						if (e.x + e.width > bounds.width)
							e.gc.fillRectangle(bounds.width, e.y, e.x + e.width
									- bounds.width + 1, e.height);
						if (e.y + e.height > bounds.height)
							e.gc.fillRectangle(e.x, bounds.height, e.width, e.y + e.height
									- bounds.height + 1);

						int width = Math.min(e.width, bounds.width - e.x);
						int height = Math.min(e.height, bounds.height - e.y);
						e.gc.drawImage(img, e.x, e.y, width, height, e.x, e.y, width,
								height);
					}
				} catch (Exception ex) {
				}
			}
		});
		Listener doNothingListener = new Listener() {
			public void handleEvent(Event event) {
			}
		};
		pieceInfoCanvas.addListener(SWT.KeyDown, doNothingListener);

		pieceInfoCanvas.addListener(SWT.Resize, new Listener() {
			public void handleEvent(Event e) {
				// wrap in asyncexec because sc.setMinWidth (called later) doesn't work
				// too well inside a resize (the canvas won't size isn't always updated)
				e.widget.getDisplay().asyncExec(new AERunnable() {
					public void runSupport() {
						if (img != null) {
							int iOldColCount = img.getBounds().width / BLOCK_SIZE;
							int iNewColCount = pieceInfoCanvas.getClientArea().width
									/ BLOCK_SIZE;
							if (iOldColCount != iNewColCount)
								refreshInfoCanvas();
						}
					}
				});
			}
		});

		sc.setContent(pieceInfoCanvas);

		Legend.createLegendComposite(pieceInfoComposite,
				blockColors, new String[] {
					"PiecesView.BlockView.Have",
					"PiecesView.BlockView.NoHave",
					"PeersView.BlockView.Transfer",
					"PeersView.BlockView.NextRequest",
					"PeersView.BlockView.AvailCount"
				}, new GridData(SWT.FILL, SWT.DEFAULT, true, false, 2, 1));

		int iFontPixelsHeight = 10;
		int iFontPointHeight = (iFontPixelsHeight * 72)
				/ pieceInfoCanvas.getDisplay().getDPI().y;
		Font f = pieceInfoCanvas.getFont();
		FontData[] fontData = f.getFontData();
		fontData[0].setHeight(iFontPointHeight);
		font = new Font(pieceInfoCanvas.getDisplay(), fontData);

		return pieceInfoComposite;
	
public voiddataSourceChanged(java.lang.Object newDataSource)

		if (newDataSource instanceof DownloadManager) {
			if (dlm != null) {
				dlm.removePeerListener(this);
			}
			dlm = (DownloadManager)newDataSource;
			dlm.addPeerListener(this, false);
			fillPieceInfoSection();
		}
	
public voiddelete()

		if (imageLabel != null && !imageLabel.isDisposed()
				&& imageLabel.getImage() != null) {
			Image image = imageLabel.getImage();
			imageLabel.setImage(null);
			image.dispose();
		}

		if (img != null && !img.isDisposed()) {
			img.dispose();
			img = null;
		}

		if (font != null && !font.isDisposed()) {
			font.dispose();
			font = null;
		}

		super.delete();
	
private voiddrawDownloadIndicator(GC gcImg, int iXPos, int iYPos, boolean small)

		if (small) {
			gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]);
			gcImg.fillPolygon(new int[] {
				iXPos + 2,
				iYPos + 2,
				iXPos + BLOCK_FILLSIZE - 1,
				iYPos + 2,
				iXPos + (BLOCK_FILLSIZE / 2),
				iYPos + BLOCK_FILLSIZE - 1
			});
		} else {
			gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]);
			gcImg.fillPolygon(new int[] {
				iXPos,
				iYPos,
				iXPos + BLOCK_FILLSIZE,
				iYPos,
				iXPos + (BLOCK_FILLSIZE / 2),
				iYPos + BLOCK_FILLSIZE
			});
		}
	
private voiddrawUploadIndicator(GC gcImg, int iXPos, int iYPos, boolean small)

		if (!small) {
			gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]);
			gcImg.fillPolygon(new int[] {
				iXPos,
				iYPos + BLOCK_FILLSIZE,
				iXPos + BLOCK_FILLSIZE,
				iYPos + BLOCK_FILLSIZE,
				iXPos + (BLOCK_FILLSIZE / 2),
				iYPos
			});
		} else {
			// Small Up Arrow each upload request
			gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]);
			gcImg.fillPolygon(new int[] {
				iXPos + 1,
				iYPos + BLOCK_FILLSIZE - 2,
				iXPos + BLOCK_FILLSIZE - 2,
				iYPos + BLOCK_FILLSIZE - 2,
				iXPos + (BLOCK_FILLSIZE / 2),
				iYPos + 2
			});
		}

	
public voidfillPieceInfoSection()


	   
		if (alreadyFilling) {
			return;
		}
		alreadyFilling = true;
		Utils.execSWTThread(new AERunnable() {
			// @see org.gudy.azureus2.core3.util.AERunnable#runSupport()
			public void runSupport() {
				try {
  				if (imageLabel == null || imageLabel.isDisposed()) {
  					return;
  				}
  
  				if (imageLabel.getImage() != null) {
  					Image image = imageLabel.getImage();
  					imageLabel.setImage(null);
  					image.dispose();
  				}
  
  				refreshInfoCanvas();
				} finally {
					alreadyFilling = false;
				}
			}
		});
	
public CompositegetComposite()

		return pieceInfoComposite;
	
public java.lang.StringgetData()

		return "PeersView.BlockView.title";
	
public voidinitialize(Composite composite)

		if (pieceInfoComposite != null && !pieceInfoComposite.isDisposed()) {
			Logger.log(new LogEvent(LogIDs.GUI, LogEvent.LT_ERROR,
					"PeerInfoView already initialized! Stack: "
							+ Debug.getStackTrace(true, false)));
			delete();
		}
		createPeerInfoPanel(composite);
		
		fillPieceInfoSection();
	
public ImageobfusticatedImage(Image image, Point shellOffset)

		UIDebugGenerator.obfusticateArea(image, topLabel, shellOffset, "");
		return image;
	
public voidpeerAdded(org.gudy.azureus2.core3.peer.PEPeer peer)

	
public voidpeerManagerAdded(org.gudy.azureus2.core3.peer.PEPeerManager manager)

	
public voidpeerManagerRemoved(org.gudy.azureus2.core3.peer.PEPeerManager manager)

	
public voidpeerManagerWillBeAdded(org.gudy.azureus2.core3.peer.PEPeerManager peer_manager)

public voidpeerRemoved(org.gudy.azureus2.core3.peer.PEPeer peer)

	
public voidpieceAdded(org.gudy.azureus2.core3.peer.PEPiece piece)

		fillPieceInfoSection();
	
public voidpieceRemoved(org.gudy.azureus2.core3.peer.PEPiece piece)

		fillPieceInfoSection();
	
public voidrefresh()

		super.refresh();

		if (loopFactor++ % graphicsUpdate == 0) {
			refreshInfoCanvas();
		}
	
protected voidrefreshInfoCanvas()

		pieceInfoCanvas.layout(true);
		Rectangle bounds = pieceInfoCanvas.getClientArea();
		if (bounds.width <= 0 || bounds.height <= 0) {
			topLabel.setText("");
			return;
		}

		if (img != null && !img.isDisposed()) {
			img.dispose();
			img = null;
		}

		if (dlm == null) {
			GC gc = new GC(pieceInfoCanvas);
			gc.fillRectangle(bounds);
			gc.dispose();
			topLabel.setText("");

			return;
		}

		DiskManagerPiece[] dm_pieces = null;

		PEPeerManager pm = dlm.getPeerManager();

		DiskManager dm = dlm.getDiskManager();

		if (pm == null || dm == null) {
			GC gc = new GC(pieceInfoCanvas);
			gc.fillRectangle(bounds);
			gc.dispose();
			topLabel.setText("");

			return;
		}

		dm_pieces = dm.getPieces();

		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 iNeededHeight = (((dm.getNbPieces() - 1) / iNumCols) + 1) * BLOCK_SIZE;
		if (sc.getMinHeight() != iNeededHeight) {
			sc.setMinHeight(iNeededHeight);
			sc.layout(true, true);
			bounds = pieceInfoCanvas.getClientArea();
		}

		int[] availability = pm.getAvailability();

		int minAvailability = Integer.MAX_VALUE;
		int minAvailability2 = Integer.MAX_VALUE;
		if (availability != null && availability.length > 0) {
			for (int i = 0; i < availability.length; i++) {
				if (availability[i] != 0 && availability[i] < minAvailability) {
					minAvailability2 = minAvailability;
					minAvailability = availability[i];
					if (minAvailability == 1) {
						break;
					}
				}
			}
		}

		img = new Image(pieceInfoCanvas.getDisplay(), bounds.width, iNeededHeight);
		GC gcImg = new GC(img);
		int iRow = 0;
		try {
			gcImg.setBackground(pieceInfoCanvas.getBackground());
			gcImg.fillRectangle(0, 0, bounds.width, iNeededHeight);

			int iCol = 0;
			for (int i = 0; i < dm_pieces.length; i++) {
				if (iCol >= iNumCols) {
					iCol = 0;
					iRow++;
				}

				int colorIndex;
				boolean done = (dm_pieces == null) ? false : dm_pieces[i].isDone();
				int iXPos = iCol * BLOCK_SIZE + 1;
				int iYPos = iRow * BLOCK_SIZE + 1;

				if (done) {
					colorIndex = BLOCKCOLOR_HAVE;

					gcImg.setBackground(blockColors[colorIndex]);
					gcImg.fillRectangle(iXPos, iYPos, BLOCK_FILLSIZE, BLOCK_FILLSIZE);
				} else {
					// !done
					boolean partiallyDone = (dm_pieces == null) ? false
							: dm_pieces[i].getNbWritten() > 0;

					int x = iXPos;
					int width = BLOCK_FILLSIZE;
					if (partiallyDone) {
						colorIndex = BLOCKCOLOR_HAVE;

						gcImg.setBackground(blockColors[colorIndex]);

						int iNewWidth = (int) (((float) dm_pieces[i].getNbWritten() / dm_pieces[i].getNbBlocks()) * width);
						if (iNewWidth >= width)
							iNewWidth = width - 1;
						else if (iNewWidth <= 0)
							iNewWidth = 1;

						gcImg.fillRectangle(x, iYPos, iNewWidth, BLOCK_FILLSIZE);
						width -= iNewWidth;
						x += iNewWidth;
					}

					colorIndex = BLOCKCOLORL_NOHAVE;

					gcImg.setBackground(blockColors[colorIndex]);
					gcImg.fillRectangle(x, iYPos, width, BLOCK_FILLSIZE);
				}

				if (Arrays.binarySearch(currentDLPieces, new Long(i), compFindPEPiece) >= 0) {
					drawDownloadIndicator(gcImg, iXPos, iYPos, false);
				}

				if (Collections.binarySearch(currentULPieces, new Long(i)) >= 0) {
					drawUploadIndicator(gcImg, iXPos, iYPos, false);
				} else if (Collections.binarySearch(futureULPieces, new Long(i)) >= 0) {
					drawUploadIndicator(gcImg, iXPos, iYPos, true);
				}

				if (availability != null) {
					if (minAvailability == availability[i]) {
						gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]);
						gcImg.drawRectangle(iXPos - 1, iYPos - 1, BLOCK_FILLSIZE + 1,
								BLOCK_FILLSIZE + 1);
					}
					if (minAvailability2 == availability[i]) {
						gcImg.setLineStyle(SWT.LINE_DOT);
						gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]);
						gcImg.drawRectangle(iXPos - 1, iYPos - 1, BLOCK_FILLSIZE + 1,
								BLOCK_FILLSIZE + 1);
						gcImg.setLineStyle(SWT.LINE_SOLID);
					}

					gcImg.setFont(font);

					String sNumber = String.valueOf(availability[i]);
					Point size = gcImg.stringExtent(sNumber);

					if (availability[i] < 100) {
						int x = iXPos + (BLOCK_FILLSIZE / 2) - (size.x / 2);
						int y = iYPos + (BLOCK_FILLSIZE / 2) - (size.y / 2);
						gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]);
						gcImg.drawText(sNumber, x, y, true);
					}
				}

				iCol++;
			}
		} catch (Exception e) {
			Logger.log(new LogEvent(LogIDs.GUI, "drawing piece map", e));
		} finally {
			gcImg.dispose();
		}

		topLabel.setText(MessageText.getString("PiecesView.BlockView.Header",
				new String[] {
					"" + iNumCols,
					"" + (iRow + 1),
					"" + dm_pieces.length
				}));

		pieceInfoCanvas.redraw();