source: trunk/eraser/Eraser/SchedulerPanel.cs @ 2057

Revision 2057, 22.8 KB checked in by lowjoel, 5 years ago (diff)

Implemented drag & drop from shell virtual folders (mainly the Recycle Bin)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
RevLine 
[1359]1/*
2 * $Id$
[1675]3 * Copyright 2008-2010 The Eraser Project
[1359]4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
[1802]24using System.Linq;
[1359]25using System.Drawing;
26using System.Text;
27using System.Windows.Forms;
28
29using System.Globalization;
30using System.Runtime.InteropServices;
31using System.Diagnostics;
32using System.IO;
33using System.Runtime.Serialization;
[1515]34using System.ComponentModel;
[1996]35
36using Eraser.Manager;
37using Eraser.Util;
[2051]38using Eraser.DefaultPlugins;
[1996]39using Microsoft.Samples;
[1802]40using ProgressChangedEventArgs = Eraser.Util.ProgressChangedEventArgs;
[1359]41
42namespace Eraser
43{
44    internal partial class SchedulerPanel : Eraser.BasePanel
45    {
46        public SchedulerPanel()
47        {
48            InitializeComponent();
[1802]49            Theming.ApplyTheme(schedulerDefaultMenu);
[1736]50            if (!IsHandleCreated)
51                CreateHandle();
[1359]52
53            //Populate the scheduler list-view with the current task list
54            ExecutorTasksCollection tasks = Program.eraserClient.Tasks;
55            foreach (Task task in tasks)
56                DisplayTask(task);
57
58            //Hook the event machinery to our class. Handle the task Added and Removed
59            //events.
60            Program.eraserClient.TaskAdded += TaskAdded;
61            Program.eraserClient.TaskDeleted += TaskDeleted;
62        }
63
64        private void DisplayTask(Task task)
65        {
66            //Add the item to the list view
67            ListViewItem item = scheduler.Items.Add(task.UIText);
68            item.SubItems.Add(string.Empty);
69            item.SubItems.Add(string.Empty);
70
71            //Set the tag of the item so we know which task on the LV corresponds
72            //to the physical task object.
73            item.Tag = task;
74
75            //Add our event handlers to the task
76            task.TaskStarted += task_TaskStarted;
77            task.ProgressChanged += task_ProgressChanged;
78            task.TaskFinished += task_TaskFinished;
79
80            //Show the fields on the list view
81            UpdateTask(item);
82        }
83
84        private void UpdateTask(ListViewItem item)
85        {
86            //Get the task object
87            Task task = (Task)item.Tag;
88
89            //Set the task name
90            item.Text = task.UIText;
91
92            //Set the next run time of the task
93            if (task.Queued)
94            {
95                item.SubItems[1].Text = S._("Queued for execution");
96                item.SubItems[2].Text = string.Empty;
97            }
98            else if (task.Schedule is RecurringSchedule)
99                item.SubItems[1].Text = ((task.Schedule as RecurringSchedule).NextRun.
100                    ToString("F", CultureInfo.CurrentCulture));
101            else if (task.Schedule == Schedule.RunNow || task.Schedule == Schedule.RunManually)
102                item.SubItems[1].Text = S._("Not queued");
103            else
104                item.SubItems[1].Text = task.Schedule.UIText;
105
106            //Set the group of the task.
107            CategorizeTask(task, item);
108        }
109
110        private void CategorizeTask(Task task)
111        {
112            CategorizeTask(task, GetTaskItem(task));
113        }
114
115        private void CategorizeTask(Task task, ListViewItem item)
116        {
117            if (task.Schedule == Schedule.RunNow || task.Schedule == Schedule.RunManually)
118                item.Group = scheduler.Groups["manual"];
119            else if (task.Schedule == Schedule.RunOnRestart)
120                item.Group = scheduler.Groups["restart"];
121            else
122                item.Group = scheduler.Groups["recurring"];
123        }
124
125        /// <summary>
126        /// Handles the Task Added event.
127        /// </summary>
128        private void TaskAdded(object sender, TaskEventArgs e)
129        {
130            if (InvokeRequired)
131            {
[1802]132                Invoke((EventHandler<TaskEventArgs>)TaskAdded, sender, e);
[1359]133                return;
134            }
135
136            //Display a balloon notification if the parent frame has been minimised.
137            MainForm parent = (MainForm)FindForm();
138            if (parent != null && (parent.WindowState == FormWindowState.Minimized || !parent.Visible))
139            {
140                parent.ShowNotificationBalloon(S._("New task added"), S._("{0} " +
141                    "has just been added to the list of tasks.", e.Task.UIText),
142                    ToolTipIcon.Info);
143            }
144
145            DisplayTask(e.Task);
146        }
147
148        private void DeleteSelectedTasks()
149        {
150            if (MessageBox.Show(this, S._("Are you sure you want to delete the selected tasks?"),
[1802]151                    S._("Eraser"), MessageBoxButtons.YesNo, MessageBoxIcon.Question,
152                    MessageBoxDefaultButton.Button1, Localisation.IsRightToLeft(this) ?
153                        MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0
154                ) != DialogResult.Yes)
[1359]155            {
156                return;
157            }
158
159            foreach (ListViewItem item in scheduler.SelectedItems)
160            {
161                Task task = (Task)item.Tag;
162                if (!task.Executing)
163                    Program.eraserClient.Tasks.Remove(task);
164            }
165        }
166
167        /// <summary>
168        /// Handles the task deleted event.
169        /// </summary>
170        private void TaskDeleted(object sender, TaskEventArgs e)
171        {
172            if (InvokeRequired)
173            {
[1802]174                Invoke((EventHandler<TaskEventArgs>)TaskDeleted, sender, e);
[1359]175                return;
176            }
177
178            foreach (ListViewItem item in scheduler.Items)
179                if (((Task)item.Tag) == e.Task)
180                {
181                    scheduler.Items.Remove(item);
182                    break;
183                }
184
185            PositionProgressBar();
186        }
187
188        /// <summary>
189        /// Handles the task start event.
190        /// </summary>
191        /// <param name="e">The task event object.</param>
[1802]192        void task_TaskStarted(object sender, EventArgs e)
[1359]193        {
[1713]194            if (InvokeRequired)
[1359]195            {
[1802]196                Invoke((EventHandler)task_TaskStarted, sender, e);
[1359]197                return;
198            }
199
200            //Get the list view item
[1802]201            Task task = (Task)sender;
202            ListViewItem item = GetTaskItem(task);
[1359]203
204            //Update the status.
205            item.SubItems[1].Text = S._("Running...");
206
207            //Show the progress bar
208            schedulerProgress.Tag = item;
209            schedulerProgress.Visible = true;
210            schedulerProgress.Value = 0;
211            PositionProgressBar();
212        }
213
214        /// <summary>
215        /// Handles the progress event by the task.
216        /// </summary>
[1515]217        void task_ProgressChanged(object sender, ProgressChangedEventArgs e)
[1359]218        {
219            //Make sure we handle the event in the main thread as this requires
220            //GUI calls.
[1713]221            if (InvokeRequired)
[1359]222            {
[1515]223                Invoke((EventHandler<ProgressChangedEventArgs>)task_ProgressChanged, sender, e);
[1359]224                return;
225            }
226
227            //Update the progress bar
[1515]228            ErasureTarget target = (ErasureTarget)sender;
229            schedulerProgress.Value = (int)(target.Task.Progress.Progress * 1000.0);
[1359]230        }
231
232        /// <summary>
233        /// Handles the task completion event.
234        /// </summary>
[1802]235        void task_TaskFinished(object sender, EventArgs e)
[1359]236        {
237            if (InvokeRequired)
238            {
[1802]239                Invoke((EventHandler)task_TaskFinished, sender, e);
[1359]240                return;
241            }
242
243            //Get the list view item
[1802]244            Task task = (Task)sender;
245            ListViewItem item = GetTaskItem(task);
[1359]246            if (item == null)
247                return;
248
249            //Hide the progress bar
250            if (schedulerProgress.Tag != null && schedulerProgress.Tag == item)
251            {
252                schedulerProgress.Tag = null;
253                schedulerProgress.Visible = false;
254            }
255
256            //Get the exit status of the task.
[1802]257            LogLevel highestLevel = task.Log.Last().Highest;
[1359]258
259            //Show a balloon to inform the user
260            MainForm parent = (MainForm)FindForm();
[1495]261            if (parent.WindowState == FormWindowState.Minimized || !parent.Visible)
[1359]262            {
263                string message = null;
264                ToolTipIcon icon = ToolTipIcon.None;
265
266                switch (highestLevel)
267                {
268                    case LogLevel.Warning:
[1802]269                        message = S._("The task {0} has completed with warnings.", task.UIText);
[1359]270                        icon = ToolTipIcon.Warning;
271                        break;
272                    case LogLevel.Error:
[1802]273                        message = S._("The task {0} has completed with errors.", task.UIText);
[1359]274                        icon = ToolTipIcon.Error;
275                        break;
276                    case LogLevel.Fatal:
[1802]277                        message = S._("The task {0} did not complete.", task.UIText);
[1359]278                        icon = ToolTipIcon.Error;
279                        break;
280                    default:
[1802]281                        message = S._("The task {0} has completed.", task.UIText);
[1359]282                        icon = ToolTipIcon.Info;
283                        break;
284                }
285
286                parent.ShowNotificationBalloon(S._("Task executed"), message,
287                    icon);
288            }
289
290            //If the user requested us to remove completed one-time tasks, do so.
291            if (EraserSettings.Get().ClearCompletedTasks &&
[1802]292                (task.Schedule == Schedule.RunNow) && highestLevel < LogLevel.Warning)
[1359]293            {
[1802]294                Program.eraserClient.Tasks.Remove(task);
[1359]295            }
296
297            //Otherwise update the UI
298            else
299            {
300                switch (highestLevel)
301                {
302                    case LogLevel.Warning:
303                        item.SubItems[2].Text = S._("Completed with warnings");
304                        break;
305                    case LogLevel.Error:
306                        item.SubItems[2].Text = S._("Completed with errors");
307                        break;
308                    case LogLevel.Fatal:
309                        item.SubItems[2].Text = S._("Not completed");
310                        break;
311                    default:
312                        item.SubItems[2].Text = S._("Completed");
313                        break;
314                }
315
316                //Recategorize the task. Do not assume the task has maintained the
317                //category since run-on-restart tasks will be changed to immediately
318                //run tasks.
[1802]319                CategorizeTask(task, item);
[1359]320
321                //Update the status of the task.
322                UpdateTask(item);
323            }
324        }
325
326        /// <summary>
327        /// Occurs when the user presses a key on the list view.
328        /// </summary>
329        /// <param name="sender">The list view which triggered the event.</param>
330        /// <param name="e">Event argument.</param>
331        private void scheduler_KeyDown(object sender, KeyEventArgs e)
332        {
333            if (e.KeyCode == Keys.Delete)
334                DeleteSelectedTasks();
335        }
336
337        /// <summary>
338        /// Occurs when the user double-clicks a scheduler item. This will result
339        /// in the log viewer being called, or the progress dialog to be displayed.
340        /// </summary>
341        /// <param name="sender">The list view which triggered the event.</param>
342        /// <param name="e">Event argument.</param>
343        private void scheduler_ItemActivate(object sender, EventArgs e)
344        {
345            if (scheduler.SelectedItems.Count == 0)
346                return;
347
348            ListViewItem item = scheduler.SelectedItems[0];
349            if (((Task)item.Tag).Executing)
350                using (ProgressForm form = new ProgressForm((Task)item.Tag))
351                    form.ShowDialog();
352            else
353                editTaskToolStripMenuItem_Click(sender, e);
354        }
355
356        /// <summary>
357        /// Occurs when the user drags a file over the scheduler
358        /// </summary>
359        private void scheduler_DragEnter(object sender, DragEventArgs e)
360        {
361            string descriptionMessage = string.Empty;
362            string descriptionInsert = string.Empty;
[2057]363            string descriptionItemFormat = S._("{0}, ");
364            const string descriptionPlaceholder = "%1";
365           
366            bool recycleBinIncluded = false;
367            List<string> files = e.Data.GetDataPresent(DataFormats.FileDrop) ?
368                new List<string>((string[])e.Data.GetData(DataFormats.FileDrop, false)) :
369                new List<string>();
370            if (e.Data.GetDataPresent("Shell IDList Array"))
[1359]371            {
[2057]372                MemoryStream stream = (MemoryStream)e.Data.GetData("Shell IDList Array");
373                byte[] buffer = new byte[stream.Length];
374                stream.Read(buffer, 0, buffer.Length);
375                ShellCIDA cida = new ShellCIDA(buffer);
376
377                if (cida.cidl > 0)
[1359]378                {
[2057]379                    for (int i = 1; i <= cida.cidl; ++i)
[1359]380                    {
[2057]381                        if (cida.aoffset[i].Guid != Guid.Empty)
[1359]382                        {
[2057]383                            if (cida.aoffset[i].Guid == Shell.KnownFolderIDs.RecycleBin)
384                            {
385                                descriptionInsert += string.Format(CultureInfo.InvariantCulture,
386                                    descriptionItemFormat, S._("Recycle Bin"));
387                                recycleBinIncluded = true;
388                            }
[1359]389                        }
390                        else
391                        {
[2057]392                            files.Add(cida.aoffset[i].Path);
[1359]393                        }
394                    }
395                }
[2057]396            }
[1359]397
[2057]398            bool isTaskList = !recycleBinIncluded;
399            foreach (string file in files)
400            {
401                if (descriptionInsert.Length < 259 &&
402                    (descriptionInsert.Length < 3 || descriptionInsert.Substring(descriptionInsert.Length - 3) != "..."))
[1359]403                {
[2057]404                    string append = string.Format(CultureInfo.InvariantCulture,
405                        descriptionItemFormat, Path.GetFileNameWithoutExtension(file));
406                    if (descriptionInsert.Length + append.Length > 259)
407                    {
408                        descriptionInsert += ".....";
409                    }
410                    else
411                    {
412                        descriptionInsert += append;
413                    }
[1359]414                }
[2057]415
416                if (Path.GetExtension(file) != ".ersx")
417                    isTaskList = false;
[1359]418            }
[2057]419            descriptionInsert = descriptionInsert.Remove(descriptionInsert.Length - 2);
[1359]420
[2057]421            if (!recycleBinIncluded && files.Count == 0)
422                e.Effect = DragDropEffects.None;
423            else if (isTaskList)
424            {
425                e.Effect = DragDropEffects.Copy;
426                descriptionMessage = S._("Import tasks from {0}", descriptionPlaceholder);
427            }
428            else
429            {
430                e.Effect = DragDropEffects.Move;
431                descriptionMessage = S._("Erase {0}", descriptionPlaceholder);
432            }
433
[1952]434            if (e.Data.GetDataPresent("DragImageBits"))
435                DropTargetHelper.DragEnter(this, e.Data, new Point(e.X, e.Y), e.Effect,
436                    descriptionMessage, descriptionInsert);
[1359]437        }
438
439        private void scheduler_DragLeave(object sender, EventArgs e)
440        {
441            DropTargetHelper.DragLeave(this);
442        }
443
444        private void scheduler_DragOver(object sender, DragEventArgs e)
445        {
446            DropTargetHelper.DragOver(new Point(e.X, e.Y), e.Effect);
447        }
448
449        /// <summary>
450        /// Occurs when the user drops a file into the scheduler.
451        /// </summary>
452        private void scheduler_DragDrop(object sender, DragEventArgs e)
453        {
[2057]454            DropTargetHelper.Drop(e.Data, new Point(e.X, e.Y), e.Effect);
455            if (e.Effect == DragDropEffects.None)
456                return;
457
458            bool recycleBinIncluded = false;
459            List<string> files = e.Data.GetDataPresent(DataFormats.FileDrop) ?
460                new List<string>((string[])e.Data.GetData(DataFormats.FileDrop, false)) :
461                new List<string>();
462            if (e.Data.GetDataPresent("Shell IDList Array"))
[2041]463            {
[2057]464                MemoryStream stream = (MemoryStream)e.Data.GetData("Shell IDList Array");
465                byte[] buffer = new byte[stream.Length];
466                stream.Read(buffer, 0, buffer.Length);
467                ShellCIDA cida = new ShellCIDA(buffer);
468
469                if (cida.cidl > 0)
470                {
471                    for (int i = 1; i <= cida.cidl; ++i)
472                    {
473                        if (cida.aoffset[i].Guid != Guid.Empty)
474                        {
475                            if (cida.aoffset[i].Guid == Shell.KnownFolderIDs.RecycleBin)
476                                recycleBinIncluded = true;
477                        }
478                        else
479                        {
480                            files.Add(cida.aoffset[i].Path);
481                        }
482                    }
483                }
[2041]484            }
485
[1996]486            //Schedule the task dialog to be shown (to get to the event loop so that
487            //ComCtl32.dll v6 is used.)
[2057]488            BeginInvoke((Action<DragDropEffects, List<string>, bool>)scheduler_DragDropConfirm,
489                e.Effect, files, recycleBinIncluded);
[1996]490        }
491
492        /// <summary>
493        /// Called after the files have been dropped into Eraser.
494        /// </summary>
495        /// <param name="effect">The Drag/drop effect of the operation.</param>
496        /// <param name="files">The files which were dropped into the program.</param>
[2057]497        /// <param name="recycleBinIncluded">True if the recycle bin was among the
498        /// items dropped.</param>
499        private void scheduler_DragDropConfirm(DragDropEffects effect, List<string> files,
500            bool recycleBinIncluded)
[1996]501        {
502            //Determine whether we are importing a task list or dragging files for
503            //erasure.
504            if (effect == DragDropEffects.Copy)
[1359]505            {
[1996]506                foreach (string file in files)
507                    using (FileStream stream = new FileStream(file, FileMode.Open,
508                        FileAccess.Read, FileShare.Read))
509                    {
510                        try
[1359]511                        {
[1996]512                            Program.eraserClient.Tasks.LoadFromStream(stream);
[1359]513                        }
[1996]514                        catch (InvalidDataException ex)
515                        {
516                            MessageBox.Show(S._("Could not import task list from {0}. The " +
517                                "error returned was: {1}", file, ex.Message), S._("Eraser"),
518                                MessageBoxButtons.OK, MessageBoxIcon.Error,
519                                MessageBoxDefaultButton.Button1,
520                                Localisation.IsRightToLeft(this) ?
521                                    MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
522                        }
523                    }
524            }
525            else if (effect == DragDropEffects.Move)
526            {
527                //Create a task with the default settings
528                Task task = new Task();
[2057]529                if (files != null)
530                    foreach (string file in files)
531                    {   
532                        FileSystemObjectErasureTarget target;
533                        if ((File.GetAttributes(file) & FileAttributes.Directory) != 0)
534                            target = new FolderErasureTarget();
535                        else
536                            target = new FileErasureTarget();
537                        target.Path = file;
[1996]538
[2057]539                        task.Targets.Add(target);
540                    }
[1996]541
[2057]542                //Add the recycle bin if it was specified
543                if (recycleBinIncluded)
544                    task.Targets.Add(new RecycleBinErasureTarget());
545
[1996]546                //Add the task, asking the user for his intent.
547                DialogResult action = DialogResult.No;
548                if (TaskDialog.IsAvailableOnThisOS)
[1359]549                {
[1996]550                    TaskDialog dialog = new TaskDialog();
551                    dialog.WindowTitle = S._("Eraser");
552                    dialog.MainIcon = TaskDialogIcon.Information;
553                    dialog.MainInstruction = S._("You have dropped a set of files and folders into Eraser. What do you want to do with them?");
554                    dialog.AllowDialogCancellation = true;
555                    dialog.Buttons = new TaskDialogButton[] {
556                        new TaskDialogButton((int)DialogResult.Yes, S._("Erase the selected items\nSchedules the selected items for immediate erasure.")),
557                        new TaskDialogButton((int)DialogResult.OK, S._("Create a new Task\nA task will be created containing the selected items.")),
558                        new TaskDialogButton((int)DialogResult.No, S._("Cancel the drag-and-drop operation"))
559                    };
560                    dialog.RightToLeftLayout = Localisation.IsRightToLeft(this);
561                    dialog.UseCommandLinks = true;
562                    action = (DialogResult)dialog.Show(this);
563                }
564                else
565                {
566                    action = MessageBox.Show(S._("Are you sure you wish to erase the selected "
567                        + "items?"), S._("Eraser"), MessageBoxButtons.YesNo,
568                        MessageBoxIcon.Question, MessageBoxDefaultButton.Button2,
569                        Localisation.IsRightToLeft(this) ?
570                            MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
571                }
[1359]572
[1996]573                switch (action)
574                {
575                    case DialogResult.OK:
576                        task.Schedule = Schedule.RunManually;
577                        goto case DialogResult.Yes;
[1359]578
[1996]579                    case DialogResult.Yes:
580                        Program.eraserClient.Tasks.Add(task);
581                        break;
[1359]582                }
583            }
584        }
585
586        /// <summary>
587        /// Occurs when the user right-clicks the list view.
588        /// </summary>
589        /// <param name="sender">The list view which generated this event.</param>
590        /// <param name="e">Event argument.</param>
591        private void schedulerMenu_Opening(object sender, CancelEventArgs e)
592        {
593            //If nothing's selected, show the Scheduler menu which just allows users to
594            //create new tasks (like from the toolbar)
595            if (scheduler.SelectedItems.Count == 0)
596            {
597                schedulerDefaultMenu.Show(schedulerMenu.Left, schedulerMenu.Top);
598                e.Cancel = true;
599                return;
600            }
601
602            bool aTaskNotQueued = false;
603            bool aTaskExecuting = false;
604            foreach (ListViewItem item in scheduler.SelectedItems)
605            {
606                Task task = (Task)item.Tag;
607                aTaskNotQueued = aTaskNotQueued || (!task.Queued && !task.Executing);
608                aTaskExecuting = aTaskExecuting || task.Executing;
609            }
610
611            runNowToolStripMenuItem.Enabled = aTaskNotQueued;
612            cancelTaskToolStripMenuItem.Enabled = aTaskExecuting;
613
614            editTaskToolStripMenuItem.Enabled = scheduler.SelectedItems.Count == 1 &&
615                !((Task)scheduler.SelectedItems[0].Tag).Executing &&
616                !((Task)scheduler.SelectedItems[0].Tag).Queued;
617            deleteTaskToolStripMenuItem.Enabled = !aTaskExecuting;
618        }
619
620        /// <summary>
621        /// Occurs when the user selects the New Task context menu item.
622        /// </summary>
623        /// <param name="sender">The menu which generated this event.</param>
624        /// <param name="e">Event argument.</param>
625        private void newTaskToolStripMenuItem_Click(object sender, EventArgs e)
626        {
627            using (TaskPropertiesForm form = new TaskPropertiesForm())
628            {
629                if (form.ShowDialog() == DialogResult.OK)
630                {
631                    Task task = form.Task;
632                    Program.eraserClient.Tasks.Add(task);
633                }
634            }
635        }
636
637        /// <summary>
638        /// Occurs whent the user selects the Run Now context menu item.
639        /// </summary>
640        /// <param name="sender">The menu which generated this event.</param>
641        /// <param name="e">Event argument.</param>
642        private void runNowToolStripMenuItem_Click(object sender, EventArgs e)
643        {
644            foreach (ListViewItem item in scheduler.SelectedItems)
645            {
646                //Queue the task
647                Task task = (Task)item.Tag;
648                if (!task.Executing && !task.Queued)
649                {
650                    Program.eraserClient.QueueTask(task);
651
652                    //Update the UI
653                    item.SubItems[1].Text = S._("Queued for execution");
654                }
655            }
656        }
657
658        /// <summary>
659        /// Occurs whent the user selects the Cancel Task context menu item.
660        /// </summary>
661        /// <param name="sender">The menu which generated this event.</param>
662        /// <param name="e">Event argument.</param>
663        private void cancelTaskToolStripMenuItem_Click(object sender, EventArgs e)
664        {
665            foreach (ListViewItem item in scheduler.SelectedItems)
666            {
667                //Queue the task
668                Task task = (Task)item.Tag;
669                if (task.Executing || task.Queued)
670                {
671                    task.Cancel();
672
673                    //Update the UI
674                    item.SubItems[1].Text = string.Empty;
675                }
676            }
677        }
678
679        /// <summary>
680        /// Occurs when the user selects the View Task Log context menu item.
681        /// </summary>
682        /// <param name="sender">The menu item which generated this event.</param>
683        /// <param name="e">Event argument.</param>
684        private void viewTaskLogToolStripMenuItem_Click(object sender, EventArgs e)
685        {
686            if (scheduler.SelectedItems.Count != 1)
687                return;
688
689            ListViewItem item = scheduler.SelectedItems[0];
690            using (LogForm form = new LogForm((Task)item.Tag))
691                form.ShowDialog();
692        }
693
694        /// <summary>
695        /// Occurs when the user selects the Edit Task context menu item.
696        /// </summary>
697        /// <param name="sender">The menu item which generated this event.</param>
698        /// <param name="e">Event argument.</param>
699        private void editTaskToolStripMenuItem_Click(object sender, EventArgs e)
700        {
701            if (scheduler.SelectedItems.Count != 1 ||
702                ((Task)scheduler.SelectedItems[0].Tag).Executing ||
703                ((Task)scheduler.SelectedItems[0].Tag).Queued)
704            {
705                return;
706            }
707
708            //Make sure that the task is not being executed, or else. This can
709            //be done in the Client library, but there will be no effect on the
710            //currently running task.
711            ListViewItem item = scheduler.SelectedItems[0];
712            Task task = (Task)item.Tag;
713            if (task.Executing)
714                return;
715
716            //Edit the task.
717            using (TaskPropertiesForm form = new TaskPropertiesForm())
718            {
719                form.Task = task;
720                if (form.ShowDialog() == DialogResult.OK)
721                {
722                    task = form.Task;
723
724                    //Update the list view
725                    UpdateTask(item);
726                }
727            }
728        }
729
730        /// <summary>
731        /// Occurs when the user selects the Delete Task context menu item.
732        /// </summary>
733        /// <param name="sender">The menu item which generated this event.</param>
734        /// <param name="e">Event argument.</param>
735        private void deleteTaskToolStripMenuItem_Click(object sender, EventArgs e)
736        {
737            DeleteSelectedTasks();
738        }
739
740        #region Item management
741        /// <summary>
742        /// Retrieves the ListViewItem for the given task.
743        /// </summary>
744        /// <param name="task">The task object whose list view entry is being sought.</param>
745        /// <returns>A ListViewItem for the given task object.</returns>
746        private ListViewItem GetTaskItem(Task task)
747        {
748            foreach (ListViewItem item in scheduler.Items)
749                if (item.Tag == task)
750                    return item;
751
752            return null;
753        }
754
755        /// <summary>
756        /// Maintains the position of the progress bar.
757        /// </summary>
758        private void PositionProgressBar()
759        {
760            if (schedulerProgress.Tag == null)
761                return;
762
763            Rectangle rect = ((ListViewItem)schedulerProgress.Tag).SubItems[2].Bounds;
[1697]764            rect.Offset(2, 2);
[1359]765            schedulerProgress.Location = rect.Location;
766            schedulerProgress.Size = rect.Size;
767        }
768
769        private void scheduler_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
770        {
771            e.DrawDefault = true;
772            if (schedulerProgress.Tag != null)
773                PositionProgressBar();
774        }
775
776        private void scheduler_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
777        {
778            e.DrawDefault = true;
779        }
780        #endregion
781    }
[1636]782}
Note: See TracBrowser for help on using the repository browser.