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

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

Forward-port from Eraser 6.0: After r2267 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            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(this, new TaskEventArgs(task));
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.