1 /*
2  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details ( see the LICENSE file ).
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 package com.aelitis.azureus.ui.swt.columns.torrent;
20 
21 import java.util.Arrays;
22 
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.graphics.*;
25 import org.eclipse.swt.widgets.*;
26 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
27 import org.gudy.azureus2.core3.download.DownloadManager;
28 import org.gudy.azureus2.core3.internat.MessageText;
29 import org.gudy.azureus2.core3.util.DisplayFormatters;
30 import org.gudy.azureus2.plugins.ui.tables.TableCellMouseEvent;
31 import org.gudy.azureus2.plugins.ui.tables.TableRowMouseEvent;
32 import org.gudy.azureus2.ui.swt.Messages;
33 import org.gudy.azureus2.ui.swt.TorrentUtil;
34 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
35 import org.gudy.azureus2.ui.swt.shells.GCStringPrinter;
36 import org.gudy.azureus2.ui.swt.views.FilesViewMenuUtil;
37 
38 import com.aelitis.azureus.ui.common.table.TableRowCore;
39 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader;
40 import com.aelitis.azureus.ui.swt.skin.SWTSkinFactory;
41 import com.aelitis.azureus.ui.swt.skin.SWTSkinProperties;
42 import com.aelitis.azureus.ui.swt.utils.ColorCache;
43 import com.aelitis.azureus.ui.swt.utils.FontUtils;
44 
45 public class ColumnTorrentFileProgress
46 {
47 
48 	private Image imgArrowButton;
49 
50 	private Image imgPriHi;
51 
52 	private Image imgPriNormal;
53 
54 	private Image imgPriStopped;
55 
56 
57 	private Image imgBGfile;
58 
59 	private Font progressFont;
60 
61 	private Display display;
62 
63 	private Color cBGdl;
64 	private Color cBGcd;
65 	private Color cBGskipped;
66 
ColumnTorrentFileProgress(Display display)67 	public ColumnTorrentFileProgress(Display display) {
68 		this.display = display;
69 
70 		ImageLoader imageLoader = ImageLoader.getInstance();
71 		imgArrowButton = imageLoader.getImage("image.fileprogress.arrowbtn");
72 		imgPriHi = imageLoader.getImage("image.fileprogress.pri.hi");
73 		imgPriNormal = imageLoader.getImage("image.fileprogress.pri.normal");
74 		imgPriStopped = imageLoader.getImage("image.fileprogress.pri.stopped");
75 		imgBGfile = imageLoader.getImage("image.progress.bg.file");
76 
77 		SWTSkinProperties skinProperties = SWTSkinFactory.getInstance().getSkinProperties();
78 		cBGdl = skinProperties.getColor("color.progress.bg.dl");
79 		if (cBGdl == null) {
80 			cBGdl = Colors.blues[Colors.BLUES_DARKEST];
81 		}
82 		cBGcd = skinProperties.getColor("color.progress.bg.cd");
83 		if (cBGcd == null) {
84 			cBGcd = Colors.green;
85 		}
86 		cBGskipped = skinProperties.getColor("color.progress.bg.cd");
87 	}
88 
fillInfoProgressETA(TableRowCore row, GC gc, DiskManagerFileInfo fileInfo, Rectangle cellArea)89 	void fillInfoProgressETA(TableRowCore row, GC gc,
90 			DiskManagerFileInfo fileInfo, Rectangle cellArea) {
91 		long percent = 0;
92 		long bytesDownloaded = fileInfo.getDownloaded();
93 		long length = fileInfo.getLength();
94 
95 		if (cBGskipped == null) {
96 			cBGskipped = ColorCache.getSchemedColor(display, "#a6bdce");
97 		}
98 
99 		if (bytesDownloaded < 0) {
100 
101 			return;
102 
103 		} else if (length == 0) {
104 
105 			percent = 1000;
106 
107 		} else if (fileInfo.getLength() != 0) {
108 
109 			percent = (1000 * bytesDownloaded) / length;
110 		}
111 
112 		gc.setAdvanced(true);
113 		gc.setTextAntialias(SWT.ON);
114 
115 		final int BUTTON_WIDTH = imgArrowButton.getBounds().width;
116 		final int HILOW_WIDTH = imgPriHi.getBounds().width;
117 		final int BUTTON_HEIGHT = imgArrowButton.getBounds().height;
118 		final int HILOW_HEIGHT = imgPriHi.getBounds().height;
119 		final int PADDING_X = 12;
120 		final int PADDING_TEXT = 5;
121 		final int PROGRESS_HEIGHT = imgBGfile.getBounds().height;
122 		final int PROGRESS_TO_HILOW_GAP = 3;
123 		final int HILOW_TO_BUTTON_GAP = 3;
124 
125 		cellArea.width -= 3;
126 
127 		int ofsX = PADDING_X;
128 		int ofsY = (cellArea.height / 2) - (PROGRESS_HEIGHT / 2) - 1;
129 		int progressWidth = cellArea.width - (ofsX * 2) - PROGRESS_TO_HILOW_GAP
130 				- HILOW_WIDTH - HILOW_TO_BUTTON_GAP - BUTTON_WIDTH;
131 
132 		if ( progressWidth > 0 ){
133 			if (progressFont == null) {
134 				progressFont = FontUtils.getFontWithHeight(gc.getFont(), gc,
135 						PROGRESS_HEIGHT - 2);
136 			}
137 			gc.setFont(progressFont);
138 			gc.setForeground(ColorCache.getSchemedColor(display, fileInfo.isSkipped()
139 					? "#95a6b2" : "#88acc1"));
140 			gc.drawRectangle(cellArea.x + ofsX, cellArea.y + ofsY - 1, progressWidth,
141 					PROGRESS_HEIGHT + 1);
142 
143 			int pctWidth = (int) (percent * (progressWidth - 1) / 1000);
144 			gc.setBackground(fileInfo.isSkipped() ? cBGskipped : percent == 1000
145 					|| fileInfo.getDownloadManager().isDownloadComplete(false) ? cBGcd
146 					: cBGdl);
147 			gc.fillRectangle(cellArea.x + ofsX + 1, cellArea.y + ofsY, pctWidth,
148 					PROGRESS_HEIGHT);
149 			gc.setBackground(Colors.white);
150 			gc.fillRectangle(cellArea.x + ofsX + pctWidth + 1, cellArea.y + ofsY,
151 					progressWidth - pctWidth - 1, PROGRESS_HEIGHT);
152 
153 			Rectangle boundsImgBG = imgBGfile.getBounds();
154 			gc.drawImage(imgBGfile, boundsImgBG.x, boundsImgBG.y, boundsImgBG.width,
155 					boundsImgBG.height, cellArea.x + ofsX + 1,
156 					cellArea.y + ofsY, progressWidth - 1, PROGRESS_HEIGHT);
157 		}
158 
159 		Color colorText = ColorCache.getSchemedColor(display, fileInfo.isSkipped()
160 				? "#556875" : "#2678b1");
161 
162 		Rectangle printBounds = new Rectangle(
163 				cellArea.x + PADDING_X + PADDING_TEXT, cellArea.y, progressWidth
164 						- (PADDING_TEXT * 2), cellArea.height);
165 		ofsY = (cellArea.height / 2) - (BUTTON_HEIGHT / 2) - 1;
166 
167 		Rectangle buttonBounds = new Rectangle(cellArea.x + cellArea.width
168 				- BUTTON_WIDTH - PADDING_X, cellArea.y + ofsY, BUTTON_WIDTH,
169 				BUTTON_HEIGHT);
170 		row.setData("buttonBounds", buttonBounds);
171 
172 		ofsY = (cellArea.height / 2) - (HILOW_HEIGHT / 2) - 1;
173 		Rectangle hilowBounds = new Rectangle(buttonBounds.x - HILOW_TO_BUTTON_GAP
174 				- HILOW_WIDTH, cellArea.y + ofsY, HILOW_WIDTH, HILOW_HEIGHT);
175 		row.setData("hilowBounds", hilowBounds);
176 
177 		gc.setForeground(colorText);
178 
179 		String s = DisplayFormatters.formatPercentFromThousands((int) percent);
180 		GCStringPrinter.printString(gc, s, printBounds, true, false, SWT.LEFT);
181 
182 		//gc.setForeground(ColorCache.getRandomColor());
183 
184 		String tmp = null;
185 		if (fileInfo.getDownloadManager().getState() == DownloadManager.STATE_STOPPED) {
186 			tmp = MessageText.getString("FileProgress.stopped");
187 		} else {
188 
189 			int st = fileInfo.getStorageType();
190 			if ((st == DiskManagerFileInfo.ST_COMPACT || st == DiskManagerFileInfo.ST_REORDER_COMPACT)
191 					&& fileInfo.isSkipped()) {
192 				tmp = MessageText.getString("FileProgress.deleted");
193 			} else if (fileInfo.isSkipped()) {
194 				tmp = MessageText.getString("FileProgress.stopped");
195 			} else if (fileInfo.getPriority() > 0) {
196 
197 				int pri = fileInfo.getPriority();
198 
199 				if (pri > 1) {
200 					tmp = MessageText.getString("FileItem.high");
201 					tmp += " (" + pri + ")";
202 				}
203 			} else {
204 				//tmp = MessageText.getString("FileItem.normal");
205 			}
206 		}
207 
208 		if (tmp != null) {
209 			GCStringPrinter.printString(gc, tmp.toUpperCase(), printBounds, false,
210 					false, SWT.RIGHT);
211 		}
212 
213 		gc.drawImage(imgArrowButton, buttonBounds.x, buttonBounds.y);
214 		Image imgPriority = fileInfo.isSkipped() ? imgPriStopped
215 				: fileInfo.getPriority() > 0 ? imgPriHi : imgPriNormal;
216 		gc.drawImage(imgPriority, hilowBounds.x, hilowBounds.y);
217 
218 		//System.out.println(cellArea + s + ";" + Debug.getCompressedStackTrace());
219 		// make relative to row, because mouse events are
220 		hilowBounds.y -= cellArea.y;
221 		hilowBounds.x -= cellArea.x;
222 		buttonBounds.x -= cellArea.x;
223 		buttonBounds.y -= cellArea.y;
224 	}
225 
fileInfoMouseTrigger(TableCellMouseEvent event)226 	public void fileInfoMouseTrigger(TableCellMouseEvent event) {
227 		if (event.eventType != TableRowMouseEvent.EVENT_MOUSEDOWN) {
228 			return;
229 		}
230 		final Object dataSource = ((TableRowCore) event.row).getDataSource(true);
231 		if (dataSource instanceof DiskManagerFileInfo) {
232 			final DiskManagerFileInfo fileInfo = (DiskManagerFileInfo) dataSource;
233 			Rectangle hilowBounds = (Rectangle) event.row.getData("hilowBounds");
234 			if (event.button == 1 && hilowBounds != null
235 					&& hilowBounds.contains(event.x, event.y)) {
236 				if (fileInfo.getPriority() > 0) {
237 					fileInfo.setPriority(0);
238 				} else {
239 					fileInfo.setPriority(1);
240 				}
241 				((TableRowCore) event.row).redraw();
242 			}
243 
244 			Rectangle buttonBounds = (Rectangle) event.row.getData("buttonBounds");
245 
246 			if (buttonBounds != null && buttonBounds.contains(event.x, event.y)) {
247 				Menu menu = new Menu(Display.getDefault().getActiveShell(), SWT.POP_UP);
248 
249 				MenuItem itemHigh = new MenuItem(menu, SWT.RADIO);
250 				Messages.setLanguageText(itemHigh, "priority.high");
251 				itemHigh.addListener(SWT.Selection, new Listener() {
252 					public void handleEvent(Event event) {
253 						FilesViewMenuUtil.changePriority(FilesViewMenuUtil.PRIORITY_HIGH,
254 								Arrays.asList(new DiskManagerFileInfo[] {
255 										fileInfo
256 								}));
257 					}
258 				});
259 				itemHigh.setSelection(fileInfo.getPriority() != 0);
260 
261 				MenuItem itemNormal = new MenuItem(menu, SWT.RADIO);
262 				Messages.setLanguageText(itemNormal, "priority.normal");
263 				itemNormal.addListener(SWT.Selection, new Listener() {
264 					public void handleEvent(Event event) {
265 						FilesViewMenuUtil.changePriority(FilesViewMenuUtil.PRIORITY_NORMAL,
266 								Arrays.asList(new DiskManagerFileInfo[] {
267 										fileInfo
268 								}));
269 					}
270 				});
271 				itemNormal.setSelection(fileInfo.getPriority() == 0);
272 
273 				new MenuItem(menu, SWT.SEPARATOR);
274 
275 				boolean canStart = fileInfo.isSkipped() || fileInfo.getDownloadManager().getState() == DownloadManager.STATE_STOPPED;
276 
277 				MenuItem itemStop = new MenuItem(menu, SWT.PUSH);
278 				Messages.setLanguageText(itemStop, "v3.MainWindow.button.stop");
279 				itemStop.addListener(SWT.Selection, new Listener() {
280 					public void handleEvent(Event event) {
281 						FilesViewMenuUtil.changePriority(
282 								FilesViewMenuUtil.PRIORITY_SKIPPED,
283 								Arrays.asList(new DiskManagerFileInfo[] {
284 										fileInfo
285 								}));
286 					}
287 				});
288 				itemStop.setEnabled(!canStart);
289 
290 				MenuItem itemStart = new MenuItem(menu, SWT.PUSH);
291 				Messages.setLanguageText(itemStart, "v3.MainWindow.button.start");
292 				itemStart.addListener(SWT.Selection, new Listener() {
293 					public void handleEvent(Event event) {
294 						if (fileInfo.getDownloadManager().getState() == DownloadManager.STATE_STOPPED) {
295 							TorrentUtil.queueDataSources(new Object[] { dataSource }, true);
296 						}
297 
298 						FilesViewMenuUtil.changePriority(FilesViewMenuUtil.PRIORITY_NORMAL,
299 								Arrays.asList(new DiskManagerFileInfo[] {
300 										fileInfo
301 								}));
302 					}
303 				});
304 				itemStart.setEnabled(canStart);
305 
306 				new MenuItem(menu, SWT.SEPARATOR);
307 
308 				MenuItem itemDelete = new MenuItem(menu, SWT.PUSH);
309 				Messages.setLanguageText(itemDelete, "v3.MainWindow.button.delete");
310 				itemDelete.addListener(SWT.Selection, new Listener() {
311 					public void handleEvent(Event event) {
312 						FilesViewMenuUtil.changePriority(FilesViewMenuUtil.PRIORITY_DELETE,
313 								Arrays.asList(new DiskManagerFileInfo[] {
314 										fileInfo
315 								}));
316 					}
317 				});
318 
319 				menu.setVisible(true);
320 				event.skipCoreFunctionality = true;
321 			}
322 			/*
323 			if (buttonBounds != null && buttonBounds.contains(event.x, event.y)) {
324 				int st = fileInfo.getStorageType();
325 				if ((st == DiskManagerFileInfo.ST_COMPACT || st == DiskManagerFileInfo.ST_REORDER_COMPACT)
326 						&& fileInfo.isSkipped()) {
327 					// deleted: Move to normal
328 					fileInfo.setPriority(0);
329 					fileInfo.setSkipped(false);
330 				} else if (fileInfo.isSkipped()) {
331 					// skipped: move to normal
332 					fileInfo.setPriority(0);
333 					fileInfo.setSkipped(false);
334 				} else if (fileInfo.getPriority() > 0) {
335 
336 					// high: move to skipped
337 					fileInfo.setSkipped(true);
338 				} else {
339 					// normal: move to high
340 					fileInfo.setPriority(1);
341 				}
342 				//((TableRowCore) event.row).invalidate();
343 				((TableRowCore) event.row).redraw();
344 			}
345 			*/
346 		}
347 	}
348 
349 }
350