source: trunk/eraser/Eraser/MainForm.cs @ 2279

Revision 2279, 12.8 KB checked in by lowjoel, 4 years ago (diff)

Fixed crash when starting Eraser from the shell extension.

  • 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.ComponentModel;
25using System.Data;
26using System.Drawing;
27using System.Drawing.Drawing2D;
28using System.Text;
29using System.Windows.Forms;
30using Eraser.Util;
31using Eraser.Manager;
32using Eraser.Properties;
33using System.IO;
34using System.Diagnostics;
35using System.Reflection;
36using System.Runtime.Serialization;
37
38namespace Eraser
39{
40    public partial class MainForm : Form
41    {
42        private BasePanel CurrPage;
43        private SchedulerPanel SchedulerPage = new SchedulerPanel();
44        private SettingsPanel SettingsPage = new SettingsPanel();
45
46        public MainForm()
47        {
48            InitializeComponent();
49            contentPanel.Controls.Add(SchedulerPage);
50            contentPanel.Controls.Add(SettingsPage);
51            if (!IsHandleCreated)
52                CreateHandle();
53
54            Theming.ApplyTheme(this);
55            Theming.ApplyTheme(notificationMenu);
56
57            //For every task we need to register the Task Started and Task Finished
58            //event handlers for progress notifications
59            foreach (Task task in Program.eraserClient.Tasks)
60                OnTaskAdded(this, new TaskEventArgs(task));
61            Program.eraserClient.TaskAdded += OnTaskAdded;
62            Program.eraserClient.TaskDeleted += OnTaskDeleted;
63
64            //Check if we have tasks running already.
65            foreach (Task task in Program.eraserClient.Tasks)
66                if (task.Executing)
67                {
68                    OnTaskProcessing(task, EventArgs.Empty);
69                    break;
70                }
71
72            //Check the notification area context menu's minimise to tray item.
73            hideWhenMinimisedToolStripMenuItem.Checked = EraserSettings.Get().HideWhenMinimised;
74
75            //Set the docking style for each of the pages
76            SchedulerPage.Dock = DockStyle.Fill;
77            SettingsPage.Visible = false;
78
79            //Show the default page.
80            ChangePage(MainFormPage.Scheduler);
81        }
82
83        /// <summary>
84        /// Diplays the given title, message and icon as a system notification area balloon.
85        /// </summary>
86        /// <param name="title">The title of the balloon.</param>
87        /// <param name="message">The message to display.</param>
88        /// <param name="icon">The icon to show.</param>
89        public void ShowNotificationBalloon(string title, string message, ToolTipIcon icon)
90        {
91            notificationIcon.BalloonTipTitle = title;
92            notificationIcon.BalloonTipText = message;
93            notificationIcon.BalloonTipIcon = icon;
94            notificationIcon.ShowBalloonTip(0);
95        }
96
97        /// <summary>
98        /// Changes the active page displayed in the form.
99        /// </summary>
100        /// <param name="page">The new page to change to. No action is done when the
101        /// current page is the same as the new page requested</param>
102        public void ChangePage(MainFormPage page)
103        {
104            BasePanel oldPage = CurrPage;
105            switch (page)
106            {
107                case MainFormPage.Scheduler:
108                    CurrPage = SchedulerPage;
109                    break;
110                case MainFormPage.Settings:
111                    CurrPage = SettingsPage;
112                    break;
113            }
114
115            if (oldPage != CurrPage)
116            {
117                contentPanel.SuspendLayout();
118
119                //Hide the old page before showing the new one
120                if (oldPage != null)
121                    oldPage.Visible = false;
122
123                //If the page is not set to dock, we need to specify the dimensions of the page
124                //so it fits properly.
125                if (CurrPage.Dock == DockStyle.None)
126                {
127                    CurrPage.Anchor = AnchorStyles.Left | AnchorStyles.Right |
128                        AnchorStyles.Top;
129                    CurrPage.Left = 0;
130                    CurrPage.Top = 0;
131                    CurrPage.Width = contentPanel.Width;
132                }
133
134                //Show the new page then bring it to the top of the z-order.
135                CurrPage.Visible = true;
136                CurrPage.BringToFront();
137                contentPanel.ResumeLayout();
138            }
139        }
140
141        private static GraphicsPath CreateRoundRect(float X, float Y, float width,
142            float height, float radius)
143        {
144            GraphicsPath result = new GraphicsPath();
145
146            //Top line.
147            result.AddLine(X + radius, Y, X + width - 2 * radius, Y);
148
149            //Top-right corner
150            result.AddArc(X + width - 2 * radius, Y, 2 * radius, 2 * radius, 270, 90);
151
152            //Right line.
153            result.AddLine(X + width, Y + radius, X + width, Y + height - 2 * radius);
154
155            //Bottom-right corner
156            result.AddArc(X + width - 2 * radius, Y + height - 2 * radius, 2 * radius, 2 * radius, 0, 90);
157
158            //Bottom line.
159            result.AddLine(X + width - 2 * radius, Y + height, X + radius, Y + height);
160
161            //Bottom-left corner
162            result.AddArc(X, Y + height - 2 *radius, 2 * radius, 2 * radius, 90, 90);
163
164            //Left line
165            result.AddLine(X, Y + height - 2 * radius, X, Y + radius);
166
167            //Top-left corner
168            result.AddArc(X, Y, 2 * radius, 2 * radius, 180, 90);
169            result.CloseFigure();
170
171            return result;
172        }
173
174        private void DrawBackground(Graphics dc)
175        {
176            //Draw the base background
177            dc.FillRectangle(new SolidBrush(Color.FromArgb(unchecked((int)0xFF292929))),
178                new Rectangle(new Point(0, 0), Size));
179
180            //Then the side gradient
181            dc.FillRectangle(new LinearGradientBrush(new Rectangle(0, 0, 338, Math.Max(1, ClientSize.Height)),
182                    Color.FromArgb(unchecked((int)0xFF363636)),
183                    Color.FromArgb(unchecked((int)0xFF292929)), 0.0),
184                0, 0, 338, ClientSize.Height);
185
186            //Draw the top background
187            dc.FillRectangle(new SolidBrush(Color.FromArgb(unchecked((int)0xFF414141))),
188                new Rectangle(0, 0, ClientSize.Width, 32));
189
190            //The top gradient
191            dc.DrawImage(Properties.Resources.BackgroundGradient, new Point(0, 0));
192
193            dc.SmoothingMode = SmoothingMode.AntiAlias;
194            dc.FillPath(Brushes.White, CreateRoundRect(11, 74, contentPanel.Width + 8, ClientSize.Height - 85, 3));
195        }
196
197        private void MainForm_Paint(object sender, PaintEventArgs e)
198        {
199            e.Graphics.SetClip(new Rectangle(0, 0, Width, Height), CombineMode.Intersect);
200            DrawBackground(e.Graphics);
201        }
202
203        private void MainForm_Resize(object sender, EventArgs e)
204        {
205            if (WindowState != FormWindowState.Minimized)
206            {
207                Bitmap bmp = new Bitmap(Width, Height);
208                Graphics dc = Graphics.FromImage(bmp);
209                DrawBackground(dc);
210
211                CreateGraphics().DrawImage(bmp, new Point(0, 0));
212            }
213            else if (EraserSettings.Get().HideWhenMinimised)
214            {
215                Visible = false;
216            }
217        }
218
219        private void tbSchedule_Click(object sender, EventArgs e)
220        {
221            ChangePage(MainFormPage.Scheduler);
222        }
223
224        private void tbSettings_Click(object sender, EventArgs e)
225        {
226            ChangePage(MainFormPage.Settings);
227        }
228
229        private void newTaskToolStripMenuItem_Click(object sender, EventArgs e)
230        {
231            using (TaskPropertiesForm form = new TaskPropertiesForm())
232            {
233                if (form.ShowDialog() == DialogResult.OK)
234                {
235                    Task task = form.Task;
236                    Program.eraserClient.Tasks.Add(task);
237                }
238            }
239        }
240
241        private void exportTaskListToolStripMenuItem_Click(object sender, EventArgs e)
242        {
243            using (SaveFileDialog dialog = new SaveFileDialog())
244            {
245                dialog.Filter = "Eraser 6 task lists (*.ersx)|*.ersx";
246                dialog.DefaultExt = "ersx";
247                dialog.OverwritePrompt = true;
248
249                if (dialog.ShowDialog() == DialogResult.OK)
250                {
251                    using (FileStream stream = new FileStream(dialog.FileName,
252                        FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
253                    {
254                        Program.eraserClient.Tasks.SaveToStream(stream);
255                    }
256                }
257            }
258        }
259
260        private void importTaskListToolStripMenuItem_Click(object sender, EventArgs e)
261        {
262            using (OpenFileDialog dialog = new OpenFileDialog())
263            {
264                dialog.Filter = "Eraser 6 task lists (*.ersx)|*.ersx";
265                dialog.DefaultExt = "ersx";
266
267                if (dialog.ShowDialog() == DialogResult.OK)
268                {
269                    using (FileStream stream = new FileStream(dialog.FileName,
270                        FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
271                    {
272                        try
273                        {
274                            Program.eraserClient.Tasks.LoadFromStream(stream);
275                        }
276                        catch (InvalidDataException ex)
277                        {
278                            MessageBox.Show(S._("The task list could not be imported. The error " +
279                                "returned was: {0}", ex.Message), S._("Eraser"),
280                                MessageBoxButtons.OK, MessageBoxIcon.Error,
281                                MessageBoxDefaultButton.Button1,
282                                Localisation.IsRightToLeft(this) ?
283                                    MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
284                        }
285                    }
286                }
287            }
288        }
289
290        private void tbHelp_Click(object sender, EventArgs e)
291        {
292            try
293            {
294                Process.Start(Path.Combine(Path.GetDirectoryName(
295                        Assembly.GetEntryAssembly().Location),
296                    "Eraser Documentation.pdf"));
297            }
298            catch (Win32Exception ex)
299            {
300                MessageBox.Show(this, S._("The Eraser documentation file could not be " +
301                    "opened. Check that Adobe Reader installed and that your Eraser " +
302                    "install is not corrupt.\n\nThe error returned was: {0}", ex.Message),
303                    S._("Eraser"), MessageBoxButtons.OK, MessageBoxIcon.Error,
304                    MessageBoxDefaultButton.Button1, Localisation.IsRightToLeft(this) ?
305                        MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
306            }
307        }
308
309        private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
310        {
311            using (UpdateForm form = new UpdateForm())
312            {
313                form.ShowDialog();
314            }
315        }
316
317        private void aboutEraserToolStripMenuItem_Click(object sender, EventArgs e)
318        {
319            using (AboutForm form = new AboutForm(this))
320            {
321                form.ShowDialog();
322            }
323        }
324
325        private void eraserLogo_Click(object sender, EventArgs e)
326        {
327            try
328            {
329                Process.Start("http://eraser.heidi.ie/");
330            }
331            catch (Win32Exception ex)
332            {
333                //We've got an error executing the the browser to pass the links: show an error
334                //to the user.
335                MessageBox.Show(S._("Could not open the required web page. The error returned " +
336                    "was: {0}", ex.Message), S._("Eraser"), MessageBoxButtons.OK,
337                    MessageBoxIcon.Error, MessageBoxDefaultButton.Button1,
338                    Localisation.IsRightToLeft(this) ?
339                        MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
340            }
341        }
342
343        #region Task processing code (for notification area animation)
344        void OnTaskAdded(object sender, TaskEventArgs e)
345        {
346            e.Task.TaskStarted += OnTaskProcessing;
347            e.Task.TaskFinished += OnTaskProcessed;
348        }
349
350        void OnTaskDeleted(object sender, TaskEventArgs e)
351        {
352            e.Task.TaskStarted -= OnTaskProcessing;
353            e.Task.TaskFinished -= OnTaskProcessed;
354        }
355
356        void OnTaskProcessing(object sender, EventArgs e)
357        {
358            if (InvokeRequired)
359            {
360                Invoke((EventHandler)OnTaskProcessing, sender, e);
361                return;
362            }
363
364            Task task = (Task)sender;
365            string iconText = S._("Eraser") + " - " + S._("Processing:") + ' ' + task.UIText;
366            if (iconText.Length >= 64)
367                iconText = iconText.Remove(60) + "...";
368
369            ProcessingAnimationFrame = 0;
370            notificationIcon.Text = iconText;
371            notificationIconTimer.Enabled = true;
372        }
373
374        void OnTaskProcessed(object sender, EventArgs e)
375        {
376            if (InvokeRequired)
377            {
378                Invoke((EventHandler)OnTaskProcessed, sender, e);
379                return;
380            }
381
382            //Reset the notification area icon.
383            notificationIconTimer.Enabled = false;
384            if (notificationIcon.Icon != null)
385            {
386                ComponentResourceManager resources = new ComponentResourceManager(typeof(MainForm));
387                resources.ApplyResources(notificationIcon, "notificationIcon");
388            }
389        }
390
391        private void notificationIconTimer_Tick(object sender, EventArgs e)
392        {
393            notificationIcon.Icon = ProcessingAnimationFrames[ProcessingAnimationFrame++];
394            if (ProcessingAnimationFrame == ProcessingAnimationFrames.Length)
395                ProcessingAnimationFrame = 0;
396        }
397
398        private int ProcessingAnimationFrame;
399        private Icon[] ProcessingAnimationFrames = new Icon[] {
400            Resources.NotifyBusy1,
401            Resources.NotifyBusy2,
402            Resources.NotifyBusy3,
403            Resources.NotifyBusy4,
404            Resources.NotifyBusy5,
405            Resources.NotifyBusy4,
406            Resources.NotifyBusy3,
407            Resources.NotifyBusy2,
408            Resources.NotifyBusy1
409        };
410        #endregion
411
412        #region Minimise to tray code
413        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
414        {
415            if (EraserSettings.Get().HideWhenMinimised && e.CloseReason == CloseReason.UserClosing)
416            {
417                e.Cancel = true;
418                Visible = false;
419            }
420        }
421
422        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
423        {
424            Application.Exit();
425        }
426
427        private void MainForm_VisibleChanged(object sender, EventArgs e)
428        {
429            if (Visible)
430            {
431                WindowState = FormWindowState.Normal;
432                Activate();
433            }
434        }
435
436        private void openToolStripMenuItem_Click(object sender, EventArgs e)
437        {
438            Visible = true;
439        }
440
441        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
442        {
443            Application.Exit();
444        }
445
446        private void hideWhenMinimiseToolStripMenuItem_Click(object sender, EventArgs e)
447        {
448            EraserSettings.Get().HideWhenMinimised =
449                hideWhenMinimisedToolStripMenuItem.Checked;
450        }
451        #endregion
452    }
453
454    public enum MainFormPage
455    {
456        Scheduler = 0,
457        Settings
458    }
459}
Note: See TracBrowser for help on using the repository browser.