/**
*
*/
package com.aelitis.azureus.ui.swt.columns.torrent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Display;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerState;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.DisplayFormatters;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.UrlUtils;
import org.gudy.azureus2.plugins.download.DownloadTypeIncomplete;
import org.gudy.azureus2.plugins.ui.menus.MenuItem;
import org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener;
import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
import org.gudy.azureus2.plugins.ui.tables.*;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
import org.gudy.azureus2.ui.swt.views.MyTorrentsView;
import org.gudy.azureus2.ui.swt.views.ViewUtils;
import org.gudy.azureus2.ui.swt.views.table.CoreTableColumnSWT;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener;
import com.aelitis.azureus.core.download.DownloadManagerEnhancer;
import com.aelitis.azureus.core.download.EnhancedDownloadManager;
import com.aelitis.azureus.ui.common.table.TableRowCore;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties;
import com.aelitis.azureus.ui.swt.utils.FontUtils;
/**
* @author TuxPaper
* @created Jun 13, 2006
*
*/
public class ColumnProgressETA
extends CoreTableColumnSWT
implements TableCellAddedListener, TableCellMouseListener,
TableCellRefreshListener, TableCellSWTPaintListener
{
public static final Class DATASOURCE_TYPE = DownloadTypeIncomplete.class;
public static final String COLUMN_ID = "ProgressETA";
private static final int borderWidth = 1;
private static final int COLUMN_WIDTH = 200;
public static final long SHOW_ETA_AFTER_MS = 30000;
private final static Object CLICK_KEY = new Object();
protected static final String CFG_SHOWETA = "ColumnProgressETA.showETA";
protected static final String CFG_SHOWSPEED = "ColumnProgressETA.showSpeed";
private static Font fontText = null;
Display display;
private Color cBGdl;
private Color cBGcd;
private Color cBorder;
private Color cText;
Color textColor;
private Image imgBGTorrent;
private Color cTextDrop;
private ViewUtils.CustomDateFormat cdf;
private ColumnTorrentFileProgress fileProgress;
protected boolean showETA;
protected boolean showSpeed;
/**
*
*/
public ColumnProgressETA(String sTableID) {
super(DATASOURCE_TYPE, COLUMN_ID, ALIGN_CENTER, COLUMN_WIDTH, sTableID);
addDataSourceType(DiskManagerFileInfo.class);
initializeAsGraphic(COLUMN_WIDTH);
setAlignment(ALIGN_LEAD);
setMinWidth(COLUMN_WIDTH);
display = SWTThread.getInstance().getDisplay();
SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties();
cBGdl = skinProperties.getColor("color.progress.bg.dl");
if (cBGdl == null) {
cBGdl = Colors.blues[Colors.BLUES_DARKEST];
}
cBGcd = skinProperties.getColor("color.progress.bg.cd");
if (cBGcd == null) {
cBGcd = Colors.green;
}
cBorder = skinProperties.getColor("color.progress.border");
if (cBorder == null) {
cBorder = Colors.grey;
}
cText = skinProperties.getColor("color.progress.text");
if (cText == null) {
cText = Colors.black;
}
cTextDrop = skinProperties.getColor("color.progress.text.drop");
cdf = ViewUtils.addCustomDateFormat(this);
ImageLoader imageLoader = ImageLoader.getInstance();
imgBGTorrent = imageLoader.getImage("image.progress.bg.torrent");
fileProgress = new ColumnTorrentFileProgress(display);
TableContextMenuItem menuShowETA = addContextMenuItem(
"ColumnProgressETA.showETA", MENU_STYLE_HEADER);
menuShowETA.setStyle(TableContextMenuItem.STYLE_CHECK);
menuShowETA.addFillListener(new MenuItemFillListener() {
public void menuWillBeShown(MenuItem menu, Object data) {
menu.setData(new Boolean(showETA));
}
});
menuShowETA.addMultiListener(new MenuItemListener() {
public void selected(MenuItem menu, Object target) {
showETA = ((Boolean) menu.getData()).booleanValue();
setUserData(CFG_SHOWETA, showETA ? 1 : 0);
}
});
TableContextMenuItem menuShowSpeed = addContextMenuItem(
"ColumnProgressETA.showSpeed", MENU_STYLE_HEADER);
menuShowSpeed.setStyle(TableContextMenuItem.STYLE_CHECK);
menuShowSpeed.addFillListener(new MenuItemFillListener() {
public void menuWillBeShown(MenuItem menu, Object data) {
menu.setData(new Boolean(showSpeed));
}
});
menuShowSpeed.addMultiListener(new MenuItemListener() {
public void selected(MenuItem menu, Object target) {
showSpeed = ((Boolean) menu.getData()).booleanValue();
setUserData(CFG_SHOWSPEED, showSpeed ? 1 : 0);
}
});
}
public void fillTableColumnInfo(TableColumnInfo info) {
info.addCategories(new String[] {
CAT_CONTENT,
CAT_ESSENTIAL,
CAT_TIME,
});
info.setProficiency(TableColumnInfo.PROFICIENCY_BEGINNER);
}
public void cellAdded(TableCell cell) {
cell.setMarginHeight(3);
cell.setMarginWidth(8);
}
public void cellMouseTrigger(TableCellMouseEvent event) {
Object ds = event.cell.getDataSource();
if (ds instanceof DiskManagerFileInfo) {
fileProgress.fileInfoMouseTrigger(event);
return;
}
DownloadManager dm = (DownloadManager) ds;
if (dm == null) {
return;
}
String clickable = (String) dm.getUserData(CLICK_KEY);
if (clickable == null) {
return;
}
event.skipCoreFunctionality = true;
if (event.eventType == TableCellMouseEvent.EVENT_MOUSEUP) {
String url = UrlUtils.getURL(clickable);
if (url != null) {
Utils.launch(url);
}
}
}
public void refresh(TableCell cell) {
Object ds = cell.getDataSource();
// needs to be long so we can shift it for sortVal
long percentDone = getPercentDone(ds);
long sortValue = 0;
if (ds instanceof DownloadManager) {
DownloadManager dm = (DownloadManager) cell.getDataSource();
// close enough to unique with abs..
int hashCode = Math.abs(DisplayFormatters.formatDownloadStatus(dm).hashCode());
long completedTime = dm.getDownloadState().getLongParameter(
DownloadManagerState.PARAM_DOWNLOAD_COMPLETED_TIME);
if (completedTime <= 0 || !dm.isDownloadComplete(false)) {
sortValue = (percentDone << 31) + hashCode;
} else {
sortValue = ((completedTime / 1000) << 31) + hashCode;
}
} else if (ds instanceof DiskManagerFileInfo) {
DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
int st = fileInfo.getStorageType();
if ((st == DiskManagerFileInfo.ST_COMPACT || st == DiskManagerFileInfo.ST_REORDER_COMPACT)
&& fileInfo.isSkipped()) {
sortValue = 1;
} else if (fileInfo.isSkipped()) {
sortValue = 2;
} else if (fileInfo.getPriority() > 0) {
int pri = fileInfo.getPriority();
sortValue = 4;
if (pri > 1) {
sortValue += pri;
}
} else {
sortValue = 3;
}
sortValue = (fileInfo.getDownloadManager().getState() * 10000)
+ percentDone + sortValue;
}
long eta = showETA ? getETA(cell) : 0;
long speed = showSpeed ? getSpeed(ds) : 0;
//System.out.println("REFRESH " + sortValue + ";" + ds);
boolean sortChanged = cell.setSortValue(sortValue);
if (sortChanged) {
UIFunctionsManagerSWT.getUIFunctionsSWT().refreshIconBar();
}
long lastETA = 0;
long lastSpeed = 0;
TableRow row = cell.getTableRow();
if (row != null) {
if (showETA) {
Object data = row.getData("lastETA");
if (data instanceof Number) {
lastETA = ((Number) data).longValue();
}
row.setData("lastETA", new Long(eta));
}
if (showSpeed) {
Object data = row.getData("lastSpeed");
if (data instanceof Number) {
lastSpeed = ((Number) data).longValue();
}
row.setData("lastSpeed", new Long(speed));
}
}
if (!sortChanged && (lastETA != eta || lastSpeed != speed)) {
cell.invalidate();
}
}
// @see org.gudy.azureus2.ui.swt.views.table.TableCellSWTPaintListener#cellPaint(org.eclipse.swt.graphics.GC, org.gudy.azureus2.ui.swt.views.table.TableCellSWT)
public void cellPaint(GC gc, TableCellSWT cell) {
Object ds = cell.getDataSource();
if (ds instanceof DiskManagerFileInfo) {
fileProgress.fillInfoProgressETA(cell.getTableRowCore(), gc,
(DiskManagerFileInfo) ds, cell.getBounds());
return;
}
if (!(ds instanceof DownloadManager)) {
return;
}
DownloadManager dm = (DownloadManager) cell.getDataSource();
int percentDone = getPercentDone(ds);
long eta = showETA ? getETA(cell) : 0;
//Compute bounds ...
int newWidth = cell.getWidth();
if (newWidth <= 0) {
return;
}
int newHeight = cell.getHeight();
Color fgFirst = gc.getForeground();
final Color fgOriginal = fgFirst;
Rectangle cellBounds = cell.getBounds();
int xStart = cellBounds.x;
int yStart = cellBounds.y;
int xRelProgressFillStart = borderWidth;
int yRelProgressFillStart = borderWidth;
int xRelProgressFillEnd = newWidth - xRelProgressFillStart - borderWidth;
int yRelProgressFillEnd = yRelProgressFillStart + 13;
boolean showSecondLine = yRelProgressFillEnd + 10 < newHeight;
if (xRelProgressFillEnd < 10 ) {
return;
}
String sStatusLine = null;
// Draw Progress bar
// ImageLoader imageLoader = ImageLoader.getInstance();
Rectangle boundsImgBG;
if (!ImageLoader.isRealImage(imgBGTorrent)) {
boundsImgBG = new Rectangle(0, 0, 0, 13);
} else {
boundsImgBG = imgBGTorrent.getBounds();
}
if (fontText == null) {
fontText = FontUtils.getFontWithHeight(gc.getFont(), gc,
boundsImgBG.height - 3);
}
if (!showSecondLine) {
yRelProgressFillStart = (cellBounds.height / 2)
- ((boundsImgBG.height) / 2);
}
yRelProgressFillEnd = yRelProgressFillStart + boundsImgBG.height;
int progressWidth = newWidth - 2;
gc.setForeground(cBorder);
gc.drawRectangle(xStart + xRelProgressFillStart - 1, yStart
+ yRelProgressFillStart - 1, progressWidth + 1, boundsImgBG.height + 1);
int pctWidth = (int) (percentDone * (progressWidth) / 1000);
gc.setBackground(percentDone == 1000 || dm.isDownloadComplete(false) ? cBGcd : cBGdl);
gc.fillRectangle(xStart + xRelProgressFillStart, yStart
+ yRelProgressFillStart, pctWidth, boundsImgBG.height);
if (progressWidth > pctWidth) {
gc.setBackground(Colors.white);
gc.fillRectangle(xStart + xRelProgressFillStart + pctWidth, yStart
+ yRelProgressFillStart, progressWidth - pctWidth, boundsImgBG.height);
}
if (boundsImgBG.width > 0) {
gc.drawImage(imgBGTorrent, 0, 0, boundsImgBG.width, boundsImgBG.height,
xStart + xRelProgressFillStart, yStart + yRelProgressFillStart,
progressWidth, boundsImgBG.height);
}
if (sStatusLine == null) {
if (dm.isUnauthorisedOnTracker()) {
sStatusLine = dm.getTrackerStatus();
// fgFirst = Colors.colorError; pftt, no colours allowed apparently
} else {
if (showETA && eta > 0) {
String sETA = ViewUtils.formatETA(eta,
MyTorrentsView.progress_eta_absolute, cdf.getDateFormat());
sStatusLine = MessageText.getString(
"MyTorrents.column.ColumnProgressETA.2ndLine", new String[] {
sETA
});
} else {
sStatusLine = DisplayFormatters.formatDownloadStatus(dm).toUpperCase();
}
}
int cursor_id;
if (sStatusLine != null && sStatusLine.indexOf("http://") == -1) {
dm.setUserData(CLICK_KEY, null);
cursor_id = SWT.CURSOR_ARROW;
} else {
dm.setUserData(CLICK_KEY, sStatusLine);
cursor_id = SWT.CURSOR_HAND;
if (!cell.getTableRow().isSelected()) {
fgFirst = Colors.blue;
}
}
((TableCellSWT) cell).setCursorID(cursor_id);
}
gc.setTextAntialias(SWT.ON);
gc.setFont(fontText);
if (showSecondLine && sStatusLine != null) {
gc.setForeground(fgFirst);
boolean over = GCStringPrinter.printString(gc, sStatusLine,
new Rectangle(cellBounds.x, yStart + yRelProgressFillEnd,
cellBounds.width, newHeight - yRelProgressFillEnd), true,
false, SWT.CENTER);
cell.setToolTip(over ? sStatusLine : null);
gc.setForeground(fgOriginal);
}
String sSpeed = "";
if (showSpeed) {
long lSpeed = getSpeed(ds);
if (lSpeed > 0) {
sSpeed = " ("
+ DisplayFormatters.formatByteCountToKiBEtcPerSec(lSpeed, true)
+ ")";
}
}
String sPercent = DisplayFormatters.formatPercentFromThousands(percentDone);
Rectangle area = new Rectangle(xStart + xRelProgressFillStart + 3, yStart
+ yRelProgressFillStart, xRelProgressFillEnd - xRelProgressFillStart
- 6, yRelProgressFillEnd - yRelProgressFillStart);
GCStringPrinter sp = new GCStringPrinter(gc, sPercent + sSpeed, area, true,
false, SWT.LEFT);
if (cTextDrop != null) {
area.x++;
area.y++;
gc.setForeground(cTextDrop);
sp.printString();
area.x--;
area.y--;
}
gc.setForeground(cText);
sp.printString();
Point pctExtent = sp.getCalculatedSize();
area.width -= (pctExtent.x + 3);
area.x += (pctExtent.x + 3);
if (!showSecondLine && sStatusLine != null) {
boolean fit = GCStringPrinter.printString(gc, sStatusLine,
area.intersection(cellBounds), true, false, SWT.RIGHT);
cell.setToolTip(fit ? null : sStatusLine);
}
gc.setFont(null);
}
private int getPercentDone(Object ds) {
if (ds instanceof DownloadManager) {
return ((DownloadManager) ds).getStats().getDownloadCompleted(true);
} else if (ds instanceof DiskManagerFileInfo) {
DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) ds;
long length = fileInfo.getLength();
if (length == 0) {
return 1000;
}
return (int) (fileInfo.getDownloaded() * 1000 / length);
}
return 0;
}
private long getETA(TableCell cell) {
Object ds = cell.getDataSource();
if (ds instanceof DiskManagerFileInfo) {
return 0;
}
DownloadManager dm = (DownloadManager) cell.getDataSource();
long diff = SystemTime.getCurrentTime() - dm.getStats().getTimeStarted();
if (diff > SHOW_ETA_AFTER_MS) {
return dm.getStats().getSmoothedETA();
}
return 0;
}
private int getState(TableCell cell) {
DownloadManager dm = (DownloadManager) cell.getDataSource();
if (dm == null) {
return DownloadManager.STATE_ERROR;
}
return dm.getState();
}
private boolean isStopped(TableCell cell) {
int state = getState(cell);
return state == DownloadManager.STATE_QUEUED
|| state == DownloadManager.STATE_STOPPED
|| state == DownloadManager.STATE_STOPPING
|| state == DownloadManager.STATE_ERROR;
}
private long getSpeed(Object ds) {
if (!(ds instanceof DownloadManager)) {
return 0;
}
return ((DownloadManager) ds).getStats().getDataReceiveRate();
}
public EnhancedDownloadManager getEDM(DownloadManager dm) {
DownloadManagerEnhancer dmEnhancer = DownloadManagerEnhancer.getSingleton();
if (dmEnhancer == null) {
return null;
}
return dmEnhancer.getEnhancedDownload(dm);
}
private void log(TableCell cell, String s) {
System.out.println(((TableRowCore) cell.getTableRow()).getIndex() + ":"
+ System.currentTimeMillis() + ": " + s);
}
public void postConfigLoad() {
super.postConfigLoad();
Object oShowETA = getUserData(CFG_SHOWETA);
if (oShowETA == null) {
showETA = false; // we could read a global default from somewhere
} else if (oShowETA instanceof Number) {
showETA = ((Number) oShowETA).intValue() == 1;
}
Object oShowSpeed = getUserData(CFG_SHOWSPEED);
if (oShowSpeed == null) {
showSpeed = false; // we could read a global default from somewhere
} else if (oShowSpeed instanceof Number) {
showSpeed = ((Number) oShowSpeed).intValue() == 1;
}
cdf.update();
}
}