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

Revision 2138, 23.2 KB checked in by lowjoel, 4 years ago (diff)

Don't create empty tasks when dragging and dropping.

  • 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 || task.Schedule == Schedule.RunNow)
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.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                        //If the path doesn't exist, skip the file
538                        if (!(File.Exists(file) || Directory.Exists(file)))
539                            continue;
540
541                        FileSystemObjectErasureTarget target;
542                        if ((File.GetAttributes(file) & FileAttributes.Directory) != 0)
543                            target = new FolderErasureTarget();
544                        else
545                            target = new FileErasureTarget();
546                        target.Path = file;
547
548                        task.Targets.Add(target);
549                    }
550
551                //Add the recycle bin if it was specified
552                if (recycleBinIncluded)
553                    task.Targets.Add(new RecycleBinErasureTarget());
554
555                //If the task has no targets, we should not go on.
556                if (task.Targets.Count == 0)
557                    return;
558
559                //Add the task, asking the user for his intent.
560                DialogResult action = DialogResult.No;
561                if (TaskDialog.IsAvailableOnThisOS)
562                {
563                    TaskDialog dialog = new TaskDialog();
564                    dialog.WindowTitle = S._("Eraser");
565                    dialog.MainIcon = TaskDialogIcon.Information;
566                    dialog.MainInstruction = S._("You have dropped a set of files and folders into Eraser. What do you want to do with them?");
567                    dialog.AllowDialogCancellation = true;
568                    dialog.Buttons = new TaskDialogButton[] {
569                        new TaskDialogButton((int)DialogResult.Yes, S._("Erase the selected items\nSchedules the selected items for immediate erasure.")),
570                        new TaskDialogButton((int)DialogResult.OK, S._("Create a new Task\nA task will be created containing the selected items.")),
571                        new TaskDialogButton((int)DialogResult.No, S._("Cancel the drag-and-drop operation"))
572                    };
573                    dialog.RightToLeftLayout = Localisation.IsRightToLeft(this);
574                    dialog.UseCommandLinks = true;
575                    action = (DialogResult)dialog.Show(this);
576                }
577                else
578                {
579                    action = MessageBox.Show(S._("Are you sure you wish to erase the selected "
580                        + "items?"), S._("Eraser"), MessageBoxButtons.YesNo,
581                        MessageBoxIcon.Question, MessageBoxDefaultButton.Button2,
582                        Localisation.IsRightToLeft(this) ?
583                            MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
584                }
585
586                switch (action)
587                {
588                    case DialogResult.OK:
589                        task.Schedule = Schedule.RunManually;
590                        goto case DialogResult.Yes;
591
592                    case DialogResult.Yes:
593                        Program.eraserClient.Tasks.Add(task);
594                        break;
595                }
596            }
597        }
598
599        /// <summary>
600        /// Occurs when the user right-clicks the list view.
601        /// </summary>
602        /// <param name="sender">The list view which generated this event.</param>
603        /// <param name="e">Event argument.</param>
604        private void schedulerMenu_Opening(object sender, CancelEventArgs e)
605        {
606            //If nothing's selected, show the Scheduler menu which just allows users to
607            //create new tasks (like from the toolbar)
608            if (scheduler.SelectedItems.Count == 0)
609            {
610                schedulerDefaultMenu.Show(schedulerMenu.Left, schedulerMenu.Top);
611                e.Cancel = true;
612                return;
613            }
614
615            bool aTaskNotQueued = false;
616            bool aTaskExecuting = false;
617            foreach (ListViewItem item in scheduler.SelectedItems)
618            {
619                Task task = (Task)item.Tag;
620                aTaskNotQueued = aTaskNotQueued || (!task.Queued && !task.Executing);
621                aTaskExecuting = aTaskExecuting || task.Executing;
622            }
623
624            runNowToolStripMenuItem.Enabled = aTaskNotQueued;
625            cancelTaskToolStripMenuItem.Enabled = aTaskExecuting;
626
627            editTaskToolStripMenuItem.Enabled = scheduler.SelectedItems.Count == 1 &&
628                !((Task)scheduler.SelectedItems[0].Tag).Executing &&
629                !((Task)scheduler.SelectedItems[0].Tag).Queued;
630            deleteTaskToolStripMenuItem.Enabled = !aTaskExecuting;
631        }
632
633        /// <summary>
634        /// Occurs when the user selects the New Task context menu item.
635        /// </summary>
636        /// <param name="sender">The menu which generated this event.</param>
637        /// <param name="e">Event argument.</param>
638        private void newTaskToolStripMenuItem_Click(object sender, EventArgs e)
639        {
640            using (TaskPropertiesForm form = new TaskPropertiesForm())
641            {
642                if (form.ShowDialog() == DialogResult.OK)
643                {
644                    Task task = form.Task;
645                    Program.eraserClient.Tasks.Add(task);
646                }
647            }
648        }
649
650        /// <summary>
651        /// Occurs whent the user selects the Run Now context menu item.
652        /// </summary>
653        /// <param name="sender">The menu which generated this event.</param>
654        /// <param name="e">Event argument.</param>
655        private void runNowToolStripMenuItem_Click(object sender, EventArgs e)
656        {
657            foreach (ListViewItem item in scheduler.SelectedItems)
658            {
659                //Queue the task
660                Task task = (Task)item.Tag;
661                if (!task.Executing && !task.Queued)
662                {
663                    Program.eraserClient.QueueTask(task);
664
665                    //Update the UI
666                    item.SubItems[1].Text = S._("Queued for execution");
667                }
668            }
669        }
670
671        /// <summary>
672        /// Occurs whent the user selects the Cancel Task context menu item.
673        /// </summary>
674        /// <param name="sender">The menu which generated this event.</param>
675        /// <param name="e">Event argument.</param>
676        private void cancelTaskToolStripMenuItem_Click(object sender, EventArgs e)
677        {
678            foreach (ListViewItem item in scheduler.SelectedItems)
679            {
680                //Queue the task
681                Task task = (Task)item.Tag;
682                if (task.Executing || task.Queued)
683                {
684                    task.Cancel();
685
686                    //Update the UI
687                    item.SubItems[1].Text = string.Empty;
688                }
689            }
690        }
691
692        /// <summary>
693        /// Occurs when the user selects the View Task Log context menu item.
694        /// </summary>
695        /// <param name="sender">The menu item which generated this event.</param>
696        /// <param name="e">Event argument.</param>
697        private void viewTaskLogToolStripMenuItem_Click(object sender, EventArgs e)
698        {
699            if (scheduler.SelectedItems.Count != 1)
700                return;
701
702            ListViewItem item = scheduler.SelectedItems[0];
703            using (LogForm form = new LogForm((Task)item.Tag))
704                form.ShowDialog();
705        }
706
707        /// <summary>
708        /// Occurs when the user selects the Edit Task context menu item.
709        /// </summary>
710        /// <param name="sender">The menu item which generated this event.</param>
711        /// <param name="e">Event argument.</param>
712        private void editTaskToolStripMenuItem_Click(object sender, EventArgs e)
713        {
714            if (scheduler.SelectedItems.Count != 1 ||
715                ((Task)scheduler.SelectedItems[0].Tag).Executing ||
716                ((Task)scheduler.SelectedItems[0].Tag).Queued)
717            {
718                return;
719            }
720
721            //Make sure that the task is not being executed, or else. This can
722            //be done in the Client library, but there will be no effect on the
723            //currently running task.
724            ListViewItem item = scheduler.SelectedItems[0];
725            Task task = (Task)item.Tag;
726            if (task.Executing)
727                return;
728
729            //Edit the task.
730            using (TaskPropertiesForm form = new TaskPropertiesForm())
731            {
732                form.Task = task;
733                if (form.ShowDialog() == DialogResult.OK)
734                {
735                    task = form.Task;
736
737                    //Update the list view
738                    UpdateTask(item);
739                }
740            }
741        }
742
743        /// <summary>
744        /// Occurs when the user selects the Delete Task context menu item.
745        /// </summary>
746        /// <param name="sender">The menu item which generated this event.</param>
747        /// <param name="e">Event argument.</param>
748        private void deleteTaskToolStripMenuItem_Click(object sender, EventArgs e)
749        {
750            DeleteSelectedTasks();
751        }
752
753        #region Item management
754        /// <summary>
755        /// Retrieves the ListViewItem for the given task.
756        /// </summary>
757        /// <param name="task">The task object whose list view entry is being sought.</param>
758        /// <returns>A ListViewItem for the given task object.</returns>
759        private ListViewItem GetTaskItem(Task task)
760        {
761            foreach (ListViewItem item in scheduler.Items)
762                if (item.Tag == task)
763                    return item;
764
765            return null;
766        }
767
768        /// <summary>
769        /// Maintains the position of the progress bar.
770        /// </summary>
771        private void PositionProgressBar()
772        {
773            if (schedulerProgress.Tag == null)
774                return;
775
776            Rectangle rect = ((ListViewItem)schedulerProgress.Tag).SubItems[2].Bounds;
777            rect.Offset(2, 2);
778            schedulerProgress.Location = rect.Location;
779            schedulerProgress.Size = rect.Size;
780        }
781
782        private void scheduler_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
783        {
784            e.DrawDefault = true;
785            if (schedulerProgress.Tag != null)
786                PositionProgressBar();
787        }
788
789        private void scheduler_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
790        {
791            e.DrawDefault = true;
792        }
793        #endregion
794    }
795}
Note: See TracBrowser for help on using the repository browser.