2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2003-2008 lfroen ( lfroen@gmail.com / http://www.amule.org )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 using System
.Collections
.Generic
;
28 using System
.ComponentModel
;
32 using System
.Windows
.Forms
;
33 using System
.Configuration
;
37 [SettingsGroupNameAttribute("XferControl")]
38 public class amuleXferControlSettings
: ApplicationSettingsBase
{
40 [DefaultSettingValueAttribute("true")]
41 public bool FilenameVisible
43 get { return (bool)this["FilenameVisible"]; }
44 set { this["FilenameVisible"] = value; }
47 [DefaultSettingValueAttribute("200")]
48 public int FilenameWidth
50 get { return (int)this["FilenameWidth"]; }
51 set { this["FilenameWidth"] = value; }
55 [DefaultSettingValueAttribute("true")]
56 public bool StatusVisible
58 get { return (bool)this["StatusVisible"]; }
59 set { this["StatusVisible"] = value; }
62 [DefaultSettingValueAttribute("100")]
63 public int StatusWidth
65 get { return (int)this["StatusWidth"]; }
66 set { this["StatusWidth"] = value; }
70 [DefaultSettingValueAttribute("true")]
71 public bool SizeVisible
73 get { return (bool)this["SizeVisible"]; }
74 set { this["StatusVisible"] = value; }
77 [DefaultSettingValueAttribute("100")]
80 get { return (int)this["SizeWidth"]; }
81 set { this["StatusWidth"] = value; }
85 [DefaultSettingValueAttribute("true")]
86 public bool SpeedVisible
88 get { return (bool)this["SpeedVisible"]; }
89 set { this["SpeedVisible"] = value; }
92 [DefaultSettingValueAttribute("100")]
95 get { return (int)this["SpeedWidth"]; }
96 set { this["SpeedWidth"] = value; }
100 [DefaultSettingValueAttribute("true")]
101 public bool CompletedVisible
103 get { return (bool)this["CompletedVisible"]; }
104 set { this["CompletedVisible"] = value; }
106 [UserScopedSetting()]
107 [DefaultSettingValueAttribute("100")]
108 public int CompletedWidth
110 get { return (int)this["CompletedWidth"]; }
111 set { this["CompletedWidth"] = value; }
114 [UserScopedSetting()]
115 [DefaultSettingValueAttribute("true")]
116 public bool SourcesVisible
118 get { return (bool)this["SourcesVisible"]; }
119 set { this["SourcesVisible"] = value; }
121 [UserScopedSetting()]
122 [DefaultSettingValueAttribute("100")]
123 public int SourcesWidth
125 get { return (int)this["SourcesWidth"]; }
126 set { this["SourcesWidth"] = value; }
130 public delegate void DownloadStatusListEventHandler();
132 public class amuleDownloadStatusList
: amuleListView
, IContainerUI
{
133 DownloadQueueContainer m_item_container
;
134 amuleXferControlSettings m_settings
= new amuleXferControlSettings();
136 enum DOWNLOAD_CTRL_COL_ID
{
147 private ContextMenuStrip m_ctx_menu
= new ContextMenuStrip();
149 public event DownloadStatusListEventHandler OnCancelItem
, OnPauseItem
, OnResumeItem
;
151 void UpdateColumnIndexes()
154 m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_FILENAME_ID
] = i
;
155 if ( m_settings
.FilenameVisible
) i
++;
156 m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
] = i
;
157 if ( m_settings
.StatusVisible
) i
++;
158 m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_SIZE_ID
] = i
;
159 if ( m_settings
.SizeVisible
) i
++;
160 m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_COMPLETED_ID
] = i
;
161 if ( m_settings
.CompletedVisible
) i
++;
162 m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_SPEED_ID
] = i
;
163 if ( m_settings
.SpeedVisible
) i
++;
164 m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_SOURCES_ID
] = i
;
165 if ( m_settings
.SourcesVisible
) i
++;
170 if ( m_settings
.FilenameVisible
) {
171 m_settings
.FilenameWidth
=
172 Columns
[m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_FILENAME_ID
]].Width
;
174 if ( m_settings
.StatusVisible
) {
175 m_settings
.StatusWidth
=
176 Columns
[(int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
].Width
;
181 public amuleDownloadStatusList()
186 new DrawListViewColumnHeaderEventHandler(amuleDownloadStatusList_DrawColumnHeader
);
188 DrawSubItem
+= new DrawListViewSubItemEventHandler(amuleDownloadStatusList_DrawSubItem
);
189 DownloadQueueItem
.InitDraw3DModifiers(FontHeight
+ 1);
191 MouseClick
+= new MouseEventHandler(amuleDownloadStatusList_MouseClickHandler
);
192 ColumnClick
+= new ColumnClickEventHandler(amuleDownloadStatusList_ColumtClickHandler
);
194 m_ctx_menu
.Opening
+= new System
.ComponentModel
.CancelEventHandler(cms_Opening
);
195 m_ctx_menu
.Items
.Add(new ToolStripLabel("Downloads"));
196 m_ctx_menu
.Items
.Add(new ToolStripSeparator());
198 ToolStripButton it_pause
= new ToolStripButton("Pause");
199 it_pause
.Click
+= new EventHandler(it_pause_Click
);
200 m_ctx_menu
.Items
.Add(it_pause
);
201 ContextMenuStrip
= m_ctx_menu
;
203 ToolStripButton it_resume
= new ToolStripButton("Resume");
204 it_resume
.Click
+= new EventHandler(it_resume_Click
);
205 m_ctx_menu
.Items
.Add(it_resume
);
207 ToolStripButton it_cancel
= new ToolStripButton("Cancel");
208 it_cancel
.Click
+= new EventHandler(it_cancel_Click
);
209 m_ctx_menu
.Items
.Add(it_cancel
);
211 m_ctx_menu
.Items
.Add(new ToolStripSeparator());
215 m_column_index
= new int[(int)DOWNLOAD_CTRL_COL_ID
.COL_LAST_ID
];
216 UpdateColumnIndexes();
218 if ( m_settings
.FilenameVisible
) {
219 CreateColumtAt("File name", m_settings
.FilenameWidth
,
220 (int)DOWNLOAD_CTRL_COL_ID
.COL_FILENAME_ID
);
222 AppendItemToCtxMenu(m_ctx_menu
, "File name", DOWNLOAD_CTRL_COL_ID
.COL_FILENAME_ID
,
223 m_settings
.FilenameVisible
, new EventHandler(column_Click
));
225 if ( m_settings
.StatusVisible
) {
226 CreateColumtAt("Status", m_settings
.StatusWidth
,
227 (int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
);
229 AppendItemToCtxMenu(m_ctx_menu
, "Status", DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
,
230 m_settings
.StatusVisible
, new EventHandler(column_Click
));
232 if ( m_settings
.SizeVisible
) {
233 CreateColumtAt("Size", m_settings
.SizeWidth
,
234 (int)DOWNLOAD_CTRL_COL_ID
.COL_SIZE_ID
);
236 AppendItemToCtxMenu(m_ctx_menu
, "Size", DOWNLOAD_CTRL_COL_ID
.COL_SIZE_ID
,
237 m_settings
.SizeVisible
, new EventHandler(column_Click
));
239 if ( m_settings
.CompletedVisible
) {
240 CreateColumtAt("Completed", m_settings
.CompletedWidth
,
241 (int)DOWNLOAD_CTRL_COL_ID
.COL_COMPLETED_ID
);
243 AppendItemToCtxMenu(m_ctx_menu
, "Completed", DOWNLOAD_CTRL_COL_ID
.COL_COMPLETED_ID
,
244 m_settings
.CompletedVisible
, new EventHandler(column_Click
));
246 if ( m_settings
.SpeedVisible
) {
247 CreateColumtAt("Speed", m_settings
.SpeedWidth
,
248 (int)DOWNLOAD_CTRL_COL_ID
.COL_SPEED_ID
);
250 AppendItemToCtxMenu(m_ctx_menu
, "Speed", DOWNLOAD_CTRL_COL_ID
.COL_SPEED_ID
,
251 m_settings
.SpeedVisible
, new EventHandler(column_Click
));
253 if ( m_settings
.SourcesVisible
) {
254 CreateColumtAt("Sources", m_settings
.SourcesWidth
,
255 m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_SOURCES_ID
]);
257 AppendItemToCtxMenu(m_ctx_menu
, "Sources", DOWNLOAD_CTRL_COL_ID
.COL_SOURCES_ID
,
258 m_settings
.SizeVisible
, new EventHandler(column_Click
));
260 ContextMenuStrip
= m_ctx_menu
;
264 // Click on column visibility checkbox in context menu
266 void column_Click(object sender
, EventArgs e
)
268 ToolStripMenuItem col
= sender
as ToolStripMenuItem
;
269 DOWNLOAD_CTRL_COL_ID col_id
= (DOWNLOAD_CTRL_COL_ID
)col
.Tag
;
270 bool status
= !col
.Checked
;
271 col
.Checked
= status
;
273 RemoveColumnAt((int)col_id
);
276 case DOWNLOAD_CTRL_COL_ID
.COL_FILENAME_ID
:
277 m_settings
.FilenameVisible
= status
;
278 UpdateColumnIndexes();
280 CreateColumtAt("File name", m_settings
.FilenameWidth
, (int)col_id
);
283 case DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
:
284 m_settings
.StatusVisible
= status
;
285 UpdateColumnIndexes();
287 CreateColumtAt("Status", m_settings
.StatusWidth
, (int)col_id
);
290 case DOWNLOAD_CTRL_COL_ID
.COL_SIZE_ID
:
291 m_settings
.SizeVisible
= status
;
292 UpdateColumnIndexes();
294 CreateColumtAt("Size", m_settings
.SizeWidth
, (int)col_id
);
297 case DOWNLOAD_CTRL_COL_ID
.COL_COMPLETED_ID
:
298 m_settings
.CompletedVisible
= status
;
299 UpdateColumnIndexes();
301 CreateColumtAt("Completed", m_settings
.CompletedWidth
, (int)col_id
);
304 case DOWNLOAD_CTRL_COL_ID
.COL_SPEED_ID
:
305 m_settings
.SpeedVisible
= status
;
306 UpdateColumnIndexes();
308 CreateColumtAt("Speed", m_settings
.SpeedWidth
, (int)col_id
);
311 case DOWNLOAD_CTRL_COL_ID
.COL_SOURCES_ID
:
312 m_settings
.SourcesVisible
= status
;
313 UpdateColumnIndexes();
315 CreateColumtAt("Sources", m_settings
.SourcesWidth
, (int)col_id
);
322 foreach ( DownloadQueueItem i
in m_item_container
.Items
) {
328 // "Cancel" command in context menu
330 void it_cancel_Click(object sender
, EventArgs e
)
336 // "Resume" command in context menu
338 void it_resume_Click(object sender
, EventArgs e
)
344 // "Pause" command in context menu
346 void it_pause_Click(object sender
, EventArgs e
)
351 public void SelectedItemsToCommand(ecProto
.ecPacket cmd
)
353 foreach ( ListViewItem i
in SelectedItems
) {
354 DownloadQueueItem it
= i
.Tag
as DownloadQueueItem
;
355 ecProto
.ecTagMD5 tag
= new ecProto
.ecTagMD5(ECTagNames
.EC_TAG_PARTFILE
, it
.ID
);
361 // Context menu - on opening. Can support dynamic menu creation
363 void cms_Opening(object sender
, System
.ComponentModel
.CancelEventArgs e
)
369 protected override void OnHandleDestroyed(EventArgs e
)
372 base.OnHandleDestroyed(e
);
374 public DownloadQueueContainer ItemContainer
376 get { return m_item_container; }
379 m_item_container
= value;
380 m_item_container
.NewItemStatusLineLength
= Columns
[1].Width
;
384 override protected void OnColumnWidthChanged(ColumnWidthChangedEventArgs e
)
386 int status_index
= m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
];
387 if ( (e
.ColumnIndex
== status_index
) && m_settings
.StatusVisible
) {
388 int new_size
= Columns
[status_index
].Width
+ 1;
389 m_item_container
.NewItemStatusLineLength
= new_size
;
391 foreach ( ListViewItem i
in Items
) {
392 DownloadQueueItem it
= i
.Tag
as DownloadQueueItem
;
393 it
.AllocColorLine(new_size
);
399 void amuleDownloadStatusList_MouseClickHandler(object o
, MouseEventArgs e
)
401 if ( e
.Button
== MouseButtons
.Right
) {
406 void amuleDownloadStatusList_ColumtClickHandler(object o
, ColumnClickEventArgs e
)
410 unsafe void DrawStatusBar(DownloadQueueItem it
, Graphics g
, Rectangle posR
)
413 // Bitmap is created as 32bpp (rgb+alpha)
415 Bitmap status_bmp
= new Bitmap(posR
.Width
, posR
.Height
,
416 System
.Drawing
.Imaging
.PixelFormat
.Format32bppArgb
);
418 System
.Drawing
.Imaging
.BitmapData bmd
= status_bmp
.LockBits(
419 new Rectangle(0, 0, status_bmp
.Width
, status_bmp
.Height
),
420 System
.Drawing
.Imaging
.ImageLockMode
.ReadWrite
,
421 System
.Drawing
.Imaging
.PixelFormat
.Format32bppArgb
);
423 RGB
[] item_color_line
= it
.ColorLine
;
424 byte[] modifiers
= DownloadQueueItem
.Get_3D_Modifiers();
426 for ( int y
= 0; y
< bmd
.Height
; y
++ ) {
427 byte* row
= (byte*)bmd
.Scan0
+ (y
* bmd
.Stride
);
429 for ( int x
= 0; x
< bmd
.Width
; x
++ ) {
430 UInt32
* pixel_ptr
= (UInt32
*)(row
+ x
* 4);
431 //row[x * 3 + 2] = 255;
432 //*pixel_ptr = 0xff0000; //RED
433 //*pixel_ptr = 0x00ff00; //GREEN
434 //*pixel_ptr = 0x1f0000ff; // BLUE
435 //*pixel_ptr = item_color_line[x] | (x << 24);
436 item_color_line
[x
].WriteToBuffWithModifier(pixel_ptr
, modifiers
[y
]);
441 status_bmp
.UnlockBits(bmd
);
443 g
.DrawImage(status_bmp
, posR
);
444 status_bmp
.Dispose();
447 void amuleDownloadStatusList_DrawSubItem(object sender
, DrawListViewSubItemEventArgs e
)
449 if ( (e
.ColumnIndex
== m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
])
450 && m_settings
.StatusVisible
) {
451 // status is colored bar
452 Rectangle r
= e
.Bounds
;
453 DownloadQueueItem it
= e
.Item
.Tag
as DownloadQueueItem
;
454 DrawStatusBar(it
, e
.Graphics
, r
);
455 e
.DrawDefault
= false;
461 if ( e
.Item
.Selected
) {
462 e
.DrawFocusRectangle(e
.Bounds
);
466 void amuleDownloadStatusList_DrawColumnHeader(object sender
, DrawListViewColumnHeaderEventArgs e
)
475 void DoInsertItem(DownloadQueueItem i
)
477 string first_col_txt
;
478 if ( m_settings
.FilenameVisible
) {
479 first_col_txt
= i
.Name
;
480 } else if ( m_settings
.StatusVisible
) {
481 first_col_txt
= i
.PercentDone
;
482 } else if ( m_settings
.SizeVisible
) {
483 first_col_txt
= i
.Size
;
484 } else if ( m_settings
.CompletedVisible
) {
485 first_col_txt
= i
.SizeDone
;
486 } else if ( m_settings
.SpeedVisible
) {
487 first_col_txt
= i
.Speed
;
488 } else if ( m_settings
.SourcesVisible
) {
489 first_col_txt
= i
.Sources
;
491 first_col_txt
= "all columns hidden";
494 ListViewItem it
= new ListViewItem(first_col_txt
);
496 if ( m_settings
.StatusVisible
) {
497 it
.SubItems
.Add(new ListViewItem
.ListViewSubItem(it
, i
.PercentDone
));
499 if ( m_settings
.SizeVisible
) {
500 it
.SubItems
.Add(new ListViewItem
.ListViewSubItem(it
, i
.Size
));
502 if ( m_settings
.CompletedVisible
) {
503 it
.SubItems
.Add(new ListViewItem
.ListViewSubItem(it
, i
.SizeDone
));
505 if ( m_settings
.SpeedVisible
) {
506 it
.SubItems
.Add(new ListViewItem
.ListViewSubItem(it
, i
.Speed
));
508 if ( m_settings
.SourcesVisible
) {
509 it
.SubItems
.Add(new ListViewItem
.ListViewSubItem(it
, i
.Sources
));
512 if ( m_settings
.StatusVisible
) {
513 it
.SubItems
[m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
]].ForeColor
= Color
.White
;
514 Columns
[(int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
].TextAlign
= HorizontalAlignment
.Center
;
524 void DoUpdateItem(DownloadQueueItem i
)
526 ListViewItem it
= i
.UiItem
as ListViewItem
;
527 int idx
= m_column_index
[(int)DOWNLOAD_CTRL_COL_ID
.COL_STATUS_ID
];
528 if ( it
.SubItems
[idx
].Text
!= i
.PercentDone
) {
529 it
.SubItems
[idx
].Text
= i
.PercentDone
;
531 idx
= (int)DOWNLOAD_CTRL_COL_ID
.COL_COMPLETED_ID
;
532 if ( it
.SubItems
[idx
].Text
!= i
.SizeDone
) {
533 it
.SubItems
[idx
].Text
= i
.SizeDone
;
535 idx
= (int)DOWNLOAD_CTRL_COL_ID
.COL_SPEED_ID
;
536 if ( it
.SubItems
[idx
].Text
!= i
.Speed
) {
537 it
.SubItems
[idx
].Text
= i
.Speed
;
542 #region IContainerUI Members
544 delegate void UpdateCallback();
546 public void MyEndUpdate()
548 if ( InvokeRequired
) {
549 UpdateCallback d
= new UpdateCallback(EndUpdate
);
557 public void MyBeginUpdate()
559 if ( InvokeRequired
) {
560 UpdateCallback d
= new UpdateCallback(BeginUpdate
);
568 delegate void ItemCallback(DownloadQueueItem i
);
570 public void InsertItem(object i
)
572 DownloadQueueItem it
= i
as DownloadQueueItem
;
573 if ( InvokeRequired
) {
574 ItemCallback d
= new ItemCallback(DoInsertItem
);
582 public void UpdateItem(object i
)
584 DownloadQueueItem it
= i
as DownloadQueueItem
;
585 if ( InvokeRequired
) {
586 ItemCallback d
= new ItemCallback(DoUpdateItem
);