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

Revision 2059, 23.0 KB checked in by lowjoel, 4 years ago (diff)

Handle cases where other shell folders, other than the recycle bin, is dropped into Eraser. Display a proper message to indicate why the drag and drop operation cannot succeed.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
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;
24using System.Linq;
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;
34using System.ComponentModel;
35
36using Eraser.Manager;
37using Eraser.Util;
38using Eraser.DefaultPlugins;
39using Microsoft.Samples;
40using ProgressChangedEventArgs = Eraser.Util.ProgressChangedEventArgs;
41
42namespace Eraser
43{
44    internal partial class SchedulerPanel : Eraser.BasePanel
45    {
46        public SchedulerPanel()
47        {
48            InitializeComponent();
49            Theming.ApplyTheme(schedulerDefaultMenu);
50            if (!IsHandleCreated)
51                CreateHandle();
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            {
132                Invoke((EventHandler<TaskEventArgs>)TaskAdded, sender, e);
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?"),
151                    S._("Eraser"), MessageBoxButtons.YesNo, MessageBoxIcon.Question,
152                    MessageBoxDefaultButton.Button1, Localisation.IsRightToLeft(this) ?
153                        MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0
154                ) != DialogResult.Yes)
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            {
174                Invoke((EventHandler<TaskEventArgs>)TaskDeleted, sender, e);
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>
192        void task_TaskStarted(object sender, EventArgs e)
193        {
194            if (InvokeRequired)
195            {
196                Invoke((EventHandler)task_TaskStarted, sender, e);
197                return;
198            }
199
200            //Get the list view item
201            Task task = (Task)sender;
202            ListViewItem item = GetTaskItem(task);
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>
217        void task_ProgressChanged(object sender, ProgressChangedEventArgs e)
218        {
219            //Make sure we handle the event in the main thread as this requires
220            //GUI calls.
221            if (InvokeRequired)
222            {
223                Invoke((EventHandler<ProgressChangedEventArgs>)task_ProgressChanged, sender, e);
224                return;
225            }
226
227            //Update the progress bar
228            ErasureTarget target = (ErasureTarget)sender;
229            schedulerProgress.Value = (int)(target.Task.Progress.Progress * 1000.0);
230        }
231
232        /// <summary>
233        /// Handles the task completion event.
234        /// </summary>
235        void task_TaskFinished(object sender, EventArgs e)
236        {
237            if (InvokeRequired)
238            {
239                Invoke((EventHandler)task_TaskFinished, sender, e);
240                return;
241            }
242
243            //Get the list view item
244            Task task = (Task)sender;
245            ListViewItem item = GetTaskItem(task);
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.
257            LogLevel highestLevel = task.Log.Last().Highest;
258
259            //Show a balloon to inform the user
260            MainForm parent = (MainForm)FindForm();
261            if (parent.WindowState == FormWindowState.Minimized || !parent.Visible)
262            {
263                string message = null;
264                ToolTipIcon icon = ToolTipIcon.None;
265
266                switch (highestLevel)
267                {
268                    case LogLevel.Warning:
269                        message = S._("The task {0} has completed with warnings.", task.UIText);
270                        icon = ToolTipIcon.Warning;
271                        break;
272                    case LogLevel.Error:
273                        message = S._("The task {0} has completed with errors.", task.UIText);
274                        icon = ToolTipIcon.Error;
275                        break;
276                    case LogLevel.Fatal:
277                        message = S._("The task {0} did not complete.", task.UIText);
278                        icon = ToolTipIcon.Error;
279                        break;
280                    default:
281                        message = S._("The task {0} has completed.", task.UIText);
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 &&
292                (task.Schedule == Schedule.RunNow) && highestLevel < LogLevel.Warning)
293            {
294                Program.eraserClient.Tasks.Remove(task);
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.
319                CategorizeTask(task, item);
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;
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"))
371            {
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)
378                {
379                    for (int i = 1; i <= cida.cidl; ++i)
380                    {
381                        if (!string.IsNullOrEmpty(cida.aoffset[i].Path))
382                        {
383                            files.Add(cida.aoffset[i].Path);
384                        }
385                        else if (cida.aoffset[i].Guid != Guid.Empty)
386                        {
387                            if (cida.aoffset[i].Guid == Shell.KnownFolderIDs.RecycleBin)
388                            {
389                                descriptionInsert += string.Format(CultureInfo.InvariantCulture,
390                                    descriptionItemFormat, S._("Recycle Bin"));
391                                recycleBinIncluded = true;
392                            }
393                        }
394                    }
395                }
396            }
397
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) != "..."))
403                {
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                    }
414                }
415
416                if (Path.GetExtension(file) != ".ersx")
417                    isTaskList = false;
418            }
419
420            if (!string.IsNullOrEmpty(descriptionInsert))
421                descriptionInsert = descriptionInsert.Remove(descriptionInsert.Length - 2);
422
423            if (!recycleBinIncluded && files.Count == 0)
424            {
425                e.Effect = DragDropEffects.None;
426                descriptionMessage = "Cannot erase the selected items";
427            }
428            else if (isTaskList)
429            {
430                e.Effect = DragDropEffects.Copy;
431                descriptionMessage = S._("Import tasks from {0}", descriptionPlaceholder);
432            }
433            else
434            {
435                e.Effect = DragDropEffects.Move;
436                descriptionMessage = S._("Erase {0}", descriptionPlaceholder);
437            }
438
439            if (e.Data.GetDataPresent("DragImageBits"))
440                DropTargetHelper.DragEnter(this, e.Data, new Point(e.X, e.Y), e.Effect,
441                    descriptionMessage, descriptionInsert);
442        }
443
444        private void scheduler_DragLeave(object sender, EventArgs e)
445        {
446            DropTargetHelper.DragLeave(this);
447        }
448
449        private void scheduler_DragOver(object sender, DragEventArgs e)
450        {
451            DropTargetHelper.DragOver(new Point(e.X, e.Y), e.Effect);
452        }
453
454        /// <summary>
455        /// Occurs when the user drops a file into the scheduler.
456        /// </summary>
457        private void scheduler_DragDrop(object sender, DragEventArgs e)
458        {
459            DropTargetHelper.Drop(e.Data, new Point(e.X, e.Y), e.Effect);
460            if (e.Effect == DragDropEffects.None)
461                return;
462
463            bool recycleBinIncluded = false;
464            List<string> files = e.Data.GetDataPresent(DataFormats.FileDrop) ?
465                new List<string>((string[])e.Data.GetData(DataFormats.FileDrop, false)) :
466                new List<string>();
467            if (e.Data.GetDataPresent("Shell IDList Array"))
468            {
469                MemoryStream stream = (MemoryStream)e.Data.GetData("Shell IDList Array");
470                byte[] buffer = new byte[stream.Length];
471                stream.Read(buffer, 0, buffer.Length);
472                ShellCIDA cida = new ShellCIDA(buffer);
473
474                if (cida.cidl > 0)
475                {
476                    for (int i = 1; i <= cida.cidl; ++i)
477                    {
478                        if (!string.IsNullOrEmpty(cida.aoffset[i].Path))
479                        {
480                            files.Add(cida.aoffset[i].Path);
481                        }
482                        else if (cida.aoffset[i].Guid != Guid.Empty)
483                        {
484                            if (cida.aoffset[i].Guid == Shell.KnownFolderIDs.RecycleBin)
485                                recycleBinIncluded = true;
486                        }
487                    }
488                }
489            }
490
491            //Schedule the task dialog to be shown (to get to the event loop so that
492            //ComCtl32.dll v6 is used.)
493            BeginInvoke((Action<DragDropEffects, List<string>, bool>)scheduler_DragDropConfirm,
494                e.Effect, files, recycleBinIncluded);
495        }
496
497        /// <summary>
498        /// Called after the files have been dropped into Eraser.
499        /// </summary>
500        /// <param name="effect">The Drag/drop effect of the operation.</param>
501        /// <param name="files">The files which were dropped into the program.</param>
502        /// <param name="recycleBinIncluded">True if the recycle bin was among the
503        /// items dropped.</param>
504        private void scheduler_DragDropConfirm(DragDropEffects effect, List<string> files,
505            bool recycleBinIncluded)
506        {
507            //Determine whether we are importing a task list or dragging files for
508            //erasure.
509            if (effect == DragDropEffects.Copy)
510            {
511                foreach (string file in files)
512                    using (FileStream stream = new FileStream(file, FileMode.Open,
513                        FileAccess.Read, FileShare.Read))
514                    {
515                        try
516                        {
517                            Program.eraserClient.Tasks.LoadFromStream(stream);
518                        }
519                        catch (InvalidDataException ex)
520                        {
521                            MessageBox.Show(S._("Could not import task list from {0}. The " +
522                                "error returned was: {1}", file, ex.Message), S._("Eraser"),
523                                MessageBoxButtons.OK, MessageBoxIcon.Error,
524                                MessageBoxDefaultButton.Button1,
525                                Localisation.IsRightToLeft(this) ?
526                                    MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
527                        }
528                    }
529            }
530            else if (effect == DragDropEffects.Move)
531            {
532                //Create a task with the default settings
533                Task task = new Task();
534                if (files != null)
535                    foreach (string file in files)
536                    {   
537                        FileSystemObjectErasureTarget target;
538                        if ((File.GetAttributes(file) & FileAttributes.Directory) != 0)
539                            target = new FolderErasureTarget();
540                        else
541                            target = new FileErasureTarget();
542                        target.Path = file;
543
544                        task.Targets.Add(target);
545                    }
546
547                //Add the recycle bin if it was specified
548                if (recycleBinIncluded)
549                    task.Targets.Add(new RecycleBinErasureTarget());
550
551                //Add the task, asking the user for his intent.
552                DialogResult action = DialogResult.No;
553                if (TaskDialog.IsAvailableOnThisOS)
554                {
555                    TaskDialog dialog = new TaskDialog();
556                    dialog.WindowTitle = S._("Eraser");
557                    dialog.MainIcon = TaskDialogIcon.Information;
558                    dialog.MainInstruction = S._("You have dropped a set of files and folders into Eraser. What do you want to do with them?");
559                    dialog.AllowDialogCancellation = true;
560                    dialog.Buttons = new TaskDialogButton[] {
561                        new TaskDialogButton((int)DialogResult.Yes, S._("Erase the selected items\nSchedules the selected items for immediate erasure.")),
562                        new TaskDialogButton((int)DialogResult.OK, S._("Create a new Task\nA task will be created containing the selected items.")),
563                        new TaskDialogButton((int)DialogResult.No, S._("Cancel the drag-and-drop operation"))
564                    };
565                    dialog.RightToLeftLayout = Localisation.IsRightToLeft(this);
566                    dialog.UseCommandLinks = true;
567                    action = (DialogResult)dialog.Show(this);
568                }
569                else
570                {
571                    action = MessageBox.Show(S._("Are you sure you wish to erase the selected "
572                        + "items?"), S._("Eraser"), MessageBoxButtons.YesNo,
573                        MessageBoxIcon.Question, MessageBoxDefaultButton.Button2,
574                        Localisation.IsRightToLeft(this) ?
575                            MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
576                }
577
578                switch (action)
579                {
580                    case DialogResult.OK:
581                        task.Schedule = Schedule.RunManually;
582                        goto case DialogResult.Yes;
583
584                    case DialogResult.Yes:
585                        Program.eraserClient.Tasks.Add(task);
586                        break;
587                }
588            }
589        }
590
591        /// <summary>
592        /// Occurs when the user right-clicks the list view.
593        /// </summary>
594        /// <param name="sender">The list view which generated this event.</param>
595        /// <param name="e">Event argument.</param>
596        private void schedulerMenu_Opening(object sender, CancelEventArgs e)
597        {
598            //If nothing's selected, show the Scheduler menu which just allows users to
599            //create new tasks (like from the toolbar)
600            if (scheduler.SelectedItems.Count == 0)
601            {
602                schedulerDefaultMenu.Show(schedulerMenu.Left, schedulerMenu.Top);
603                e.Cancel = true;
604                return;
605            }
606
607            bool aTaskNotQueued = false;
608            bool aTaskExecuting = false;
609            foreach (ListViewItem item in scheduler.SelectedItems)
610            {
611                Task task = (Task)item.Tag;
612                aTaskNotQueued = aTaskNotQueued || (!task.Queued && !task.Executing);
613                aTaskExecuting = aTaskExecuting || task.Executing;
614            }
615
616            runNowToolStripMenuItem.Enabled = aTaskNotQueued;
617            cancelTaskToolStripMenuItem.Enabled = aTaskExecuting;
618
619            editTaskToolStripMenuItem.Enabled = scheduler.SelectedItems.Count == 1 &&
620                !((Task)scheduler.SelectedItems[0].Tag).Executing &&
621                !((Task)scheduler.SelectedItems[0].Tag).Queued;
622            deleteTaskToolStripMenuItem.Enabled = !aTaskExecuting;
623        }
624
625        /// <summary>
626        /// Occurs when the user selects the New Task context menu item.
627        /// </summary>
628        /// <param name="sender">The menu which generated this event.</param>
629        /// <param name="e">Event argument.</param>
630        private void newTaskToolStripMenuItem_Click(object sender, EventArgs e)
631        {
632            using (TaskPropertiesForm form = new TaskPropertiesForm())
633            {
634                if (form.ShowDialog() == DialogResult.OK)
635                {
636                    Task task = form.Task;
637                    Program.eraserClient.Tasks.Add(task);
638                }
639            }
640        }
641
642        /// <summary>
643        /// Occurs whent the user selects the Run Now context menu item.
644        /// </summary>
645        /// <param name="sender">The menu which generated this event.</param>
646        /// <param name="e">Event argument.</param>
647        private void runNowToolStripMenuItem_Click(object sender, EventArgs e)
648        {
649            foreach (ListViewItem item in scheduler.SelectedItems)
650            {
651                //Queue the task
652                Task task = (Task)item.Tag;
653                if (!task.Executing && !task.Queued)
654                {
655                    Program.eraserClient.QueueTask(task);
656
657                    //Update the UI
658                    item.SubItems[1].Text = S._("Queued for execution");
659                }
660            }
661        }
662
663        /// <summary>
664        /// Occurs whent the user selects the Cancel Task context menu item.
665        /// </summary>
666        /// <param name="sender">The menu which generated this event.</param>
667        /// <param name="e">Event argument.</param>
668        private void cancelTaskToolStripMenuItem_Click(object sender, EventArgs e)
669        {
670            foreach (ListViewItem item in scheduler.SelectedItems)
671            {
672                //Queue the task
673                Task task = (Task)item.Tag;
674                if (task.Executing || task.Queued)
675                {
676                    task.Cancel();
677
678                    //Update the UI
679                    item.SubItems[1].Text = string.Empty;
680                }
681            }
682        }
683
684        /// <summary>
685        /// Occurs when the user selects the View Task Log context menu item.
686        /// </summary>
687        /// <param name="sender">The menu item which generated this event.</param>
688        /// <param name="e">Event argument.</param>
689        private void viewTaskLogToolStripMenuItem_Click(object sender, EventArgs e)
690        {
691            if (scheduler.SelectedItems.Count != 1)
692                return;
693
694            ListViewItem item = scheduler.SelectedItems[0];
695            using (LogForm form = new LogForm((Task)item.Tag))
696                form.ShowDialog();
697        }
698
699        /// <summary>
700        /// Occurs when the user selects the Edit Task context menu item.
701        /// </summary>
702        /// <param name="sender">The menu item which generated this event.</param>
703        /// <param name="e">Event argument.</param>
704        private void editTaskToolStripMenuItem_Click(object sender, EventArgs e)
705        {
706            if (scheduler.SelectedItems.Count != 1 ||
707                ((Task)scheduler.SelectedItems[0].Tag).Executing ||
708                ((Task)scheduler.SelectedItems[0].Tag).Queued)
709            {
710                return;
711            }
712
713            //Make sure that the task is not being executed, or else. This can
714            //be done in the Client library, but there will be no effect on the
715            //currently running task.
716            ListViewItem item = scheduler.SelectedItems[0];
717            Task task = (Task)item.Tag;
718            if (task.Executing)
719                return;
720
721            //Edit the task.
722            using (TaskPropertiesForm form = new TaskPropertiesForm())
723            {
724                form.Task = task;
725                if (form.ShowDialog() == DialogResult.OK)
726                {
727                    task = form.Task;
728
729                    //Update the list view
730                    UpdateTask(item);
731                }
732            }
733        }
734
735        /// <summary>
736        /// Occurs when the user selects the Delete Task context menu item.
737        /// </summary>
738        /// <param name="sender">The menu item which generated this event.</param>
739        /// <param name="e">Event argument.</param>
740        private void deleteTaskToolStripMenuItem_Click(object sender, EventArgs e)
741        {
742            DeleteSelectedTasks();
743        }
744
745        #region Item management
746        /// <summary>
747        /// Retrieves the ListViewItem for the given task.
748        /// </summary>
749        /// <param name="task">The task object whose list view entry is being sought.</param>
750        /// <returns>A ListViewItem for the given task object.</returns>
751        private ListViewItem GetTaskItem(Task task)
752        {
753            foreach (ListViewItem item in scheduler.Items)
754                if (item.Tag == task)
755                    return item;
756
757            return null;
758        }
759
760        /// <summary>
761        /// Maintains the position of the progress bar.
762        /// </summary>
763        private void PositionProgressBar()
764        {
765            if (schedulerProgress.Tag == null)
766                return;
767
768            Rectangle rect = ((ListViewItem)schedulerProgress.Tag).SubItems[2].Bounds;
769            rect.Offset(2, 2);
770            schedulerProgress.Location = rect.Location;
771            schedulerProgress.Size = rect.Size;
772        }
773
774        private void scheduler_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
775        {
776            e.DrawDefault = true;
777            if (schedulerProgress.Tag != null)
778                PositionProgressBar();
779        }
780
781        private void scheduler_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
782        {
783            e.DrawDefault = true;
784        }
785        #endregion
786    }
787}
Note: See TracBrowser for help on using the repository browser.