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

Revision 1734, 11.1 KB checked in by lowjoel, 4 years ago (diff)

Fixed potential regression in r1721 and r1633 where we added in calls to CreateHandle? so that window handles are created immediately for calls to InvokeRequired?. Move those calls to the start of the constructor so that the handle will not be already created and throw an InvalidOperationException?

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