/*
* File : PiecesItem.java
* Created : 24 nov. 2003
* By : Olivier
*
* Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details ( see the LICENSE file ).
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* AELITIS, SAS au capital de 46,603.30 euros,
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*/
package org.gudy.azureus2.ui.swt.views.tableitems.peers;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.gudy.azureus2.core3.disk.*;
import org.gudy.azureus2.core3.peer.PEPeer;
import org.gudy.azureus2.core3.peer.impl.PEPeerTransport;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;
import com.aelitis.azureus.core.peermanager.piecepicker.util.BitFlags;
import org.gudy.azureus2.plugins.ui.Graphic;
import org.gudy.azureus2.plugins.ui.tables.*;
/**
*
* @author Olivier
* @author TuxPaper (2004/Apr/19: modified to TableCellAdapter)
*/
public class PiecesItem
extends CoreTableColumn
implements TableCellAddedListener, TableCellRefreshListener, TableCellDisposeListener, DiskManagerListener
{
private final static int INDEX_COLOR_FADEDSTARTS = Colors.BLUES_DARKEST + 1;
// only supports 0 or 1 border width
private final static int borderHorizontalSize = 1;
private final static int borderVerticalSize = 1;
private final static int borderSplit = 1;
private final static int completionHeight = 2;
private int row_count;
/** Default Constructor */
public PiecesItem(String table_id) {
super("pieces", table_id);
initializeAsGraphic(POSITION_LAST, 200);
}
public void fillTableColumnInfo(TableColumnInfo info) {
info.addCategories(new String[] {
CAT_CONTENT,
});
}
public void cellAdded(TableCell cell) {
synchronized( this ){
row_count++;
}
cell.setFillCell(true);
Object ds = cell.getDataSource();
if (ds instanceof PEPeer) {
PEPeer peer = (PEPeer) ds;
DiskManager diskmanager = peer.getManager().getDiskManager();
if ( diskmanager.getRemaining() > 0 ){
if ( !diskmanager.hasListener( this )){
diskmanager.addListener( this );
}
}
}
}
public void dispose(TableCell cell) {
synchronized( this ){
row_count--;
}
// Named infoObj so code can be copied easily to the other PiecesItem
PEPeer infoObj = (PEPeer)cell.getDataSource();
if (infoObj == null)
return;
Image img = (Image)infoObj.getData("PiecesImage");
if (img != null && !img.isDisposed())
img.dispose();
infoObj.setData("PiecesImageBuffer", null);
infoObj.setData("PiecesImage", null);
}
public void refresh(TableCell cell) {
/* Notes:
* We store our image and imageBufer in PEPeer using
* setData & getData.
*/
// Named infoObj so code can be copied easily to the other PiecesItem
PEPeer infoObj = (PEPeer)cell.getDataSource();
long lCompleted = (infoObj == null) ? 0 : infoObj.getPercentDoneInThousandNotation();
if( !cell.setSortValue( lCompleted ) && cell.isValid() ) {
return;
}
if (infoObj == null)
return;
//Compute bounds ...
int newWidth = cell.getWidth();
if (newWidth <= 0)
return;
int newHeight = cell.getHeight();
int x0 = borderVerticalSize;
int x1 = newWidth - 1 - borderVerticalSize;
int y0 = completionHeight + borderHorizontalSize + borderSplit;
int y1 = newHeight - 1 - borderHorizontalSize;
int drawWidth = x1 - x0 + 1;
if (drawWidth < 10 || y1 < 3)
return;
int[] imageBuffer = (int [])infoObj.getData("PiecesImageBuffer");
boolean bImageBufferValid = imageBuffer != null && imageBuffer.length == drawWidth;
Image image = (Image)infoObj.getData("PiecesImage");
GC gcImage;
boolean bImageChanged;
Rectangle imageBounds;
if (image == null || image.isDisposed()) {
bImageChanged = true;
} else {
imageBounds = image.getBounds();
bImageChanged = imageBounds.width != newWidth ||
imageBounds.height != newHeight;
}
if (bImageChanged) {
if (image != null && !image.isDisposed()) {
image.dispose();
}
image = new Image(SWTThread.getInstance().getDisplay(),
newWidth, newHeight);
imageBounds = image.getBounds();
bImageBufferValid = false;
// draw border
gcImage = new GC(image);
gcImage.setForeground(Colors.grey);
if (borderHorizontalSize > 0) {
if (borderVerticalSize > 0) {
gcImage.drawRectangle(0, 0, newWidth - 1, newHeight - 1);
} else {
gcImage.drawLine(0, 0, newWidth - 1, 0);
gcImage.drawLine(0, newHeight -1, newWidth - 1, newHeight - 1);
}
} else if (borderVerticalSize > 0) {
gcImage.drawLine(0, 0, 0, newHeight - 1);
gcImage.drawLine(newWidth - 1, 0, newWidth - 1, newHeight - 1);
}
if (borderSplit > 0) {
gcImage.setForeground(Colors.white);
gcImage.drawLine(x0, completionHeight + borderHorizontalSize,
x1, completionHeight + borderHorizontalSize);
}
} else {
gcImage = new GC(image);
}
final BitFlags peerHave = infoObj.getAvailable();
boolean established = ((PEPeerTransport)infoObj).getConnectionState() == PEPeerTransport.CONNECTION_FULLY_ESTABLISHED;
if (established && peerHave != null && peerHave.flags.length > 0) {
if (imageBuffer == null || imageBuffer.length != drawWidth) {
imageBuffer = new int[drawWidth];
}
final boolean available[] =peerHave.flags;
try {
int nbComplete = 0;
int nbPieces = available.length;
DiskManager disk_manager = infoObj.getManager().getDiskManager();
DiskManagerPiece[] pieces = disk_manager==null?null:disk_manager.getPieces();
int a0;
int a1 = 0;
for (int i = 0; i < drawWidth; i++) {
if (i == 0) {
// always start out with one piece
a0 = 0;
a1 = nbPieces / drawWidth;
if (a1 == 0)
a1 = 1;
} else {
// the last iteration, a1 will be nbPieces
a0 = a1;
a1 = ((i + 1) * nbPieces) / (drawWidth);
}
int index;
int nbNeeded = 0;
if (a1 <= a0) {
index = imageBuffer[i - 1];
} else {
int nbAvailable = 0;
for (int j = a0; j < a1; j++) {
if (available[j]) {
if (pieces==null || !pieces[j].isDone()) {
nbNeeded++;
}
nbAvailable++;
}
}
nbComplete += nbAvailable;
index = (nbAvailable * Colors.BLUES_DARKEST) / (a1 - a0);
if (nbNeeded <= nbAvailable / 2)
index += INDEX_COLOR_FADEDSTARTS;
}
if (imageBuffer[i] != index) {
imageBuffer[i] = index;
if (bImageBufferValid) {
bImageChanged = true;
if (imageBuffer[i] >= INDEX_COLOR_FADEDSTARTS)
gcImage.setForeground(Colors.faded[index - INDEX_COLOR_FADEDSTARTS]);
else
gcImage.setForeground(Colors.blues[index]);
gcImage.drawLine(i + x0, y0, i + x0, y1);
}
}
}
if (!bImageBufferValid) {
if(established) {
int iLastIndex = imageBuffer[0];
int iWidth = 1;
for (int i = 1; i < drawWidth; i++) {
if (iLastIndex == imageBuffer[i]) {
iWidth++;
} else {
if (iLastIndex >= INDEX_COLOR_FADEDSTARTS) {
gcImage.setBackground(Colors.faded[iLastIndex - INDEX_COLOR_FADEDSTARTS]);
} else
gcImage.setBackground(Colors.blues[iLastIndex]);
gcImage.fillRectangle(i - iWidth + x0, y0, iWidth, y1 - y0 + 1);
iWidth = 1;
iLastIndex = imageBuffer[i];
}
}
if (iLastIndex >= INDEX_COLOR_FADEDSTARTS)
gcImage.setBackground(Colors.faded[iLastIndex - INDEX_COLOR_FADEDSTARTS]);
else
gcImage.setBackground(Colors.blues[iLastIndex]);
gcImage.fillRectangle(x1 - iWidth + 1, y0, iWidth, y1 - y0 + 1);
bImageChanged = true;
}
}
int limit = (drawWidth * nbComplete) / nbPieces;
if (limit < drawWidth) {
gcImage.setBackground(Colors.blues[Colors.BLUES_LIGHTEST]);
gcImage.fillRectangle(limit+x0, borderHorizontalSize,
x1-limit, completionHeight);
}
gcImage.setBackground(Colors.colorProgressBar);
gcImage.fillRectangle(x0, borderHorizontalSize,
limit, completionHeight);
} catch (Exception e) {
System.out.println("Error Drawing PiecesItem");
Debug.printStackTrace( e );
} } else {
gcImage.setForeground(Colors.grey);
gcImage.setBackground(Colors.grey);
gcImage.fillRectangle(x0,y0,newWidth,y1);
}
gcImage.dispose();
Image oldImage = null;
Graphic graphic = cell.getGraphic();
if (graphic instanceof UISWTGraphic) {
oldImage = ((UISWTGraphic) graphic).getImage();
}
if (bImageChanged || image != oldImage || !cell.isValid()) {
if (cell instanceof TableCellSWT) {
((TableCellSWT) cell).setGraphic(image);
} else {
cell.setGraphic(new UISWTGraphicImpl(image));
}
if (bImageChanged || image != oldImage) {
cell.invalidate();
}
infoObj.setData("PiecesImage", image);
infoObj.setData("PiecesImageBuffer", imageBuffer);
}
}
// @see org.gudy.azureus2.core3.disk.DiskManagerListener#fileAccessModeChanged(org.gudy.azureus2.core3.disk.DiskManagerFileInfo, int, int)
public void fileAccessModeChanged(DiskManagerFileInfo file, int old_mode,
int new_mode) {
}
// @see org.gudy.azureus2.core3.disk.DiskManagerListener#filePriorityChanged(org.gudy.azureus2.core3.disk.DiskManagerFileInfo)
public void filePriorityChanged(DiskManagerFileInfo file) {
}
// @see org.gudy.azureus2.core3.disk.DiskManagerListener#pieceDoneChanged(org.gudy.azureus2.core3.disk.DiskManagerPiece)
public void pieceDoneChanged(DiskManagerPiece piece) {
DiskManager diskmanager = piece.getManager();
boolean remove_listener;
synchronized( this ){
remove_listener = row_count==0;
}
if ( remove_listener ){
diskmanager.removeListener( this );
}else{
invalidateCells();
if ( diskmanager.getRemaining() == 0 ){
diskmanager.removeListener(this);
}
}
}
// @see org.gudy.azureus2.core3.disk.DiskManagerListener#stateChanged(int, int)
public void stateChanged(int oldState, int newState) {
}
}