source: branches/eraser6/6.0/Eraser/MainForm.cs @ 2265

Revision 2265, 12.6 KB checked in by lowjoel, 4 years ago (diff)

After r2263 where the Executor runs before the creation of the main window, we can no longer assume that the executor is not running when the controls are created. Always check and update the UI when starting.

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