From 013fa89ce430cbc975a3457ed6cfc597c295b146 Mon Sep 17 00:00:00 2001 From: Mark Lopez Date: Sun, 2 Nov 2014 13:00:02 -0700 Subject: [PATCH] Removed P/Invokes, now uses native ContextMenu handling. --- SparkleShare/Windows/SparkleNotifyIcon.cs | 377 +++++------------ .../Windows/SparkleShare.sln.DotSettings | 3 +- SparkleShare/Windows/SparkleStatusIcon.cs | 388 +++++++++--------- 3 files changed, 306 insertions(+), 462 deletions(-) diff --git a/SparkleShare/Windows/SparkleNotifyIcon.cs b/SparkleShare/Windows/SparkleNotifyIcon.cs index e097c13b..d8730179 100644 --- a/SparkleShare/Windows/SparkleNotifyIcon.cs +++ b/SparkleShare/Windows/SparkleNotifyIcon.cs @@ -17,12 +17,9 @@ using System; using System.ComponentModel; -using System.Diagnostics; using System.Runtime.InteropServices; -using System.Threading; using System.Windows; using System.Windows.Controls; -using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Markup; @@ -33,330 +30,158 @@ namespace SparkleShare { [ContentProperty("Text")] [DefaultEvent("MouseDoubleClick")] - public class SparkleNotifyIcon : FrameworkElement, IAddChild { - - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - private static extern IntPtr GetModuleHandle(string module_name); - - [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - private static extern int CallNextHookEx (int hook_id, int code, int param, IntPtr data_pointer); - - [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - private static extern int SetWindowsHookEx (int hook_id, HookProc function, IntPtr instance, int thread_id); + public class SparkleNotifyIcon : UIElement, IAddChild { [DllImport("user32.dll", EntryPoint = "DestroyIcon")] - static extern bool DestroyIcon (IntPtr hIcon); - - [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)] - private static extern int UnhookWindowsHookEx (int hook_id); + static extern bool DestroyIcon(IntPtr h_icon); - [StructLayout (LayoutKind.Sequential)] - private struct MouseLLHook - { - internal int X; - internal int Y; - internal int MouseData; - internal int Flags; - internal int Time; - internal int Info; - } - - public Drawing.Bitmap Icon { set { - this.notify_icon.Icon = GetIconFromBitmap (value); + NotifyIcon.Icon = GetIconFromBitmap(value); } } + public string Text { + get { + return (string) GetValue(TextProperty); + } + set { + var text = value; + + if(!string.IsNullOrEmpty(HeaderText)) + text = HeaderText + "\n" + text; + + SetValue(TextProperty, text); + } + } + + public ContextMenu ContextMenu { + get; + set; + } + public string HeaderText { - get { - return header_text; - } - - set { - header_text = value; - } - } - - public string Text { - get { - return (string) GetValue (TextProperty); - } - - set { - string text = value; - - if (!string.IsNullOrEmpty (header_text)) - text = header_text + "\n" + text; - - SetValue (TextProperty, text); - } + get; + set; } - public event MouseButtonEventHandler MouseClick { - add { - AddHandler (MouseClickEvent, value); - } - - remove { - RemoveHandler (MouseClickEvent, value); - } + private Forms.NotifyIcon NotifyIcon { + get; + set; } - public event MouseButtonEventHandler MouseDoubleClick { - add { - AddHandler (MouseDoubleClickEvent, value); - } - - remove { - RemoveHandler (MouseDoubleClickEvent, value); - } - } - - - public readonly RoutedEvent MouseClickEvent = EventManager.RegisterRoutedEvent ( - "MouseClick", RoutingStrategy.Bubble, typeof (MouseButtonEventHandler), typeof (SparkleNotifyIcon)); + public readonly RoutedEvent MouseClickEvent = EventManager.RegisterRoutedEvent( + "MouseClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(SparkleNotifyIcon)); public readonly RoutedEvent MouseDoubleClickEvent = EventManager.RegisterRoutedEvent( - "MouseDoubleClick", RoutingStrategy.Bubble, typeof (MouseButtonEventHandler), typeof (SparkleNotifyIcon)); + "MouseDoubleClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(SparkleNotifyIcon)); public readonly DependencyProperty TextProperty = DependencyProperty.Register( - "Text", typeof(string), typeof (SparkleNotifyIcon), new PropertyMetadata (OnTextChanged)); + "Text", typeof(string), typeof(SparkleNotifyIcon), new PropertyMetadata(OnTextChanged)); - - private string header_text; - private Forms.NotifyIcon notify_icon; - private HookProc hook_proc_ref; - private int mouse_hook_handle; - private delegate int HookProc (int code, int param, IntPtr struct_pointer); - - - public SparkleNotifyIcon () - { - VisibilityProperty.OverrideMetadata (typeof (SparkleNotifyIcon), - new PropertyMetadata (OnVisibilityChanged)); - - this.notify_icon = new Forms.NotifyIcon () { - Text = Text, - Visible = true + public SparkleNotifyIcon() { + VisibilityProperty.OverrideMetadata(typeof(SparkleNotifyIcon), new PropertyMetadata(OnVisibilityChanged)); + + NotifyIcon = new Forms.NotifyIcon { + Text = Text, + Visible = true, + ContextMenu = new Forms.ContextMenu() }; - - this.notify_icon.MouseDown += OnMouseDown; - this.notify_icon.MouseUp += OnMouseUp; - this.notify_icon.MouseClick += OnMouseClick; - this.notify_icon.MouseDoubleClick += OnMouseDoubleClick; - - this.hook_proc_ref = OnMouseEventProc; + NotifyIcon.MouseDown += OnMouseDown; + NotifyIcon.MouseUp += OnMouseUp; + NotifyIcon.MouseClick += OnMouseClick; + NotifyIcon.MouseDoubleClick += OnMouseDoubleClick; } - - - public void ShowBalloonTip (string title, string subtext, string image_path) - { + + public void ShowBalloonTip(string title, string subtext, string image_path) { // TODO: // - Use the image pointed to by image_path // - Find a way to use the prettier (Win7?) balloons - this.notify_icon.ShowBalloonTip (5 * 1000, title, subtext, Forms.ToolTipIcon.Info); + NotifyIcon.ShowBalloonTip(5 * 1000, title, subtext, Forms.ToolTipIcon.Info); } - - public void Dispose() - { - this.notify_icon.Dispose(); + public void Dispose() { + NotifyIcon.Dispose(); } - void IAddChild.AddChild (object value) - { - throw new InvalidOperationException (); + void IAddChild.AddChild(object value) { + throw new InvalidOperationException(); } - - void IAddChild.AddText (string text) - { - if (text == null) - throw new ArgumentNullException (); + void IAddChild.AddText(string text) { + if(text == null) + throw new ArgumentNullException(); Text = text; } - - private static MouseButtonEventArgs CreateMouseButtonEventArgs( - RoutedEvent handler, Forms.MouseButtons button) - { + private static MouseButtonEventArgs CreateMouseButtonEventArgs(RoutedEvent handler, Forms.MouseButtons button) { MouseButton mouse_button; - if (button == Forms.MouseButtons.Left) { + if(button == Forms.MouseButtons.Left) { mouse_button = MouseButton.Left; - - } else if (button == Forms.MouseButtons.Right) { + + } else if(button == Forms.MouseButtons.Right) { mouse_button = MouseButton.Right; - - } else if (button == Forms.MouseButtons.Middle) { + + } else if(button == Forms.MouseButtons.Middle) { mouse_button = MouseButton.Middle; - - } else if (button == Forms.MouseButtons.XButton1) { + + } else if(button == Forms.MouseButtons.XButton1) { mouse_button = MouseButton.XButton1; - - } else if (button == Forms.MouseButtons.XButton2) { + + } else if(button == Forms.MouseButtons.XButton2) { mouse_button = MouseButton.XButton2; - + } else { - throw new InvalidOperationException (); + throw new InvalidOperationException(); } - return new MouseButtonEventArgs (InputManager.Current.PrimaryMouseDevice, 0, mouse_button) { + return new MouseButtonEventArgs(InputManager.Current.PrimaryMouseDevice, 0, mouse_button) { RoutedEvent = handler }; } - - private void ShowContextMenu () - { - if (ContextMenu != null) { - ContextMenu.Opened += OnContextMenuOpened; - ContextMenu.Closed += OnContextMenuClosed; - - ContextMenu.Placement = PlacementMode.Mouse; - ContextMenu.IsOpen = true; - } - } - - - private Rect GetContextMenuRect (ContextMenu menu) - { - var source = PresentationSource.FromVisual (menu); - if (source != null) { - Point start_point = menu.PointToScreen(new Point(0, 0)); - Point end_point = menu.PointToScreen(new Point(menu.ActualWidth, menu.ActualHeight)); - - return new Rect(start_point, end_point); - } - - return new Rect(); - } - - - private Point GetHitPoint (IntPtr struct_pointer) - { - MouseLLHook mouse_hook = (MouseLLHook) Marshal.PtrToStructure ( - struct_pointer, typeof (MouseLLHook)); - - return new Point (mouse_hook.X, mouse_hook.Y); - } - - - private int OnMouseEventProc (int code, int button, IntPtr data_pointer) - { - int left_button_down = 0x201; - int right_button_down = 0x204; - - int ret; - try { - if (button == left_button_down || button == right_button_down) - { - Rect context_menu_rect = GetContextMenuRect (ContextMenu); - Point hit_point = GetHitPoint (data_pointer); - - if (!context_menu_rect.Contains(hit_point)) { - new Thread (() => { - Thread.Sleep (750); - - Dispatcher.BeginInvoke ((Action) delegate { - ContextMenu.IsOpen = false; - }); - }).Start (); - } - } - } - finally { - ret = CallNextHookEx(this.mouse_hook_handle, code, button, data_pointer); - } - - return ret; - } - - - private void OnContextMenuOpened (object sender, RoutedEventArgs args) - { - using (Process process = Process.GetCurrentProcess ()) - using (ProcessModule module = process.MainModule) - { - this.mouse_hook_handle = SetWindowsHookEx (14, this.hook_proc_ref, - GetModuleHandle (module.ModuleName), 0); - } - - if (this.mouse_hook_handle == 0) - throw new Win32Exception (Marshal.GetLastWin32Error ()); - } - - - private void OnContextMenuClosed (object sender, RoutedEventArgs args) - { - UnhookWindowsHookEx (this.mouse_hook_handle); - - ContextMenu.Opened -= OnContextMenuOpened; - ContextMenu.Closed -= OnContextMenuClosed; - } - - - private void OnVisibilityChanged (DependencyObject target, - DependencyPropertyChangedEventArgs args) - { - SparkleNotifyIcon control = (SparkleNotifyIcon) target; - control.notify_icon.Visible = (control.Visibility == Visibility.Visible); - } - - - private void OnMouseDown(object sender, Forms.MouseEventArgs args) - { - RaiseEvent (CreateMouseButtonEventArgs (MouseDownEvent, args.Button)); - } - - - private void OnMouseClick (object sender, Forms.MouseEventArgs args) - { - RaiseEvent (CreateMouseButtonEventArgs (MouseClickEvent, args.Button)); - } - - - private void OnMouseDoubleClick (object sender, Forms.MouseEventArgs args) - { - RaiseEvent (CreateMouseButtonEventArgs (MouseDoubleClickEvent, args.Button)); - } - - - private void OnMouseUp (object sender, Forms.MouseEventArgs args) - { - if (args.Button == Forms.MouseButtons.Left || - args.Button == Forms.MouseButtons.Right) { - - ShowContextMenu (); - } - - RaiseEvent (CreateMouseButtonEventArgs (MouseUpEvent, args.Button)); - } - - - protected override void OnVisualParentChanged (DependencyObject parent) - { - base.OnVisualParentChanged (parent); - } - - - private static void OnTextChanged (DependencyObject target, - DependencyPropertyChangedEventArgs args) - { + private void OnVisibilityChanged(DependencyObject target, DependencyPropertyChangedEventArgs args) { SparkleNotifyIcon control = (SparkleNotifyIcon) target; - control.notify_icon.Text = control.Text; + control.NotifyIcon.Visible = (control.Visibility == Visibility.Visible); } - - private Drawing.Icon GetIconFromBitmap (Drawing.Bitmap bitmap) - { - IntPtr unmanaged_icon = bitmap.GetHicon (); - Drawing.Icon icon = (Drawing.Icon) Drawing.Icon.FromHandle (unmanaged_icon).Clone (); - DestroyIcon (unmanaged_icon); - + private void OnMouseDown(object sender, Forms.MouseEventArgs args) { + RaiseEvent(CreateMouseButtonEventArgs(MouseDownEvent, args.Button)); + } + + private void OnMouseClick(object sender, Forms.MouseEventArgs args) { + RaiseEvent(CreateMouseButtonEventArgs(MouseClickEvent, args.Button)); + } + + private void OnMouseDoubleClick(object sender, Forms.MouseEventArgs args) { + RaiseEvent(CreateMouseButtonEventArgs(MouseDoubleClickEvent, args.Button)); + } + + private void OnMouseUp(object sender, Forms.MouseEventArgs args) { + + if(args.Button == Forms.MouseButtons.Right) { + + ContextMenu.IsOpen = true; + ContextMenu.StaysOpen = false; + } + + RaiseEvent(CreateMouseButtonEventArgs(MouseUpEvent, args.Button)); + } + + private static void OnTextChanged(DependencyObject target, DependencyPropertyChangedEventArgs args) { + SparkleNotifyIcon control = (SparkleNotifyIcon) target; + control.NotifyIcon.Text = control.Text; + } + + + private static Drawing.Icon GetIconFromBitmap(Drawing.Bitmap bitmap) { + IntPtr unmanaged_icon = bitmap.GetHicon(); + Drawing.Icon icon = (Drawing.Icon) Drawing.Icon.FromHandle(unmanaged_icon).Clone(); + DestroyIcon(unmanaged_icon); + return icon; } } diff --git a/SparkleShare/Windows/SparkleShare.sln.DotSettings b/SparkleShare/Windows/SparkleShare.sln.DotSettings index c0f5f065..b6bc0642 100644 --- a/SparkleShare/Windows/SparkleShare.sln.DotSettings +++ b/SparkleShare/Windows/SparkleShare.sln.DotSettings @@ -14,4 +14,5 @@ True True <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> \ No newline at end of file + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + True \ No newline at end of file diff --git a/SparkleShare/Windows/SparkleStatusIcon.cs b/SparkleShare/Windows/SparkleStatusIcon.cs index 31847195..a6854f9b 100644 --- a/SparkleShare/Windows/SparkleStatusIcon.cs +++ b/SparkleShare/Windows/SparkleStatusIcon.cs @@ -17,291 +17,309 @@ using System; using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; using System.Windows.Media.Imaging; -using System.Windows.Media; using System.Windows.Controls; -using System.Windows.Controls.Primitives; using Drawing = System.Drawing; -using Forms = System.Windows.Forms; namespace SparkleShare { public class SparkleStatusIcon : Control { - + public SparkleStatusIconController Controller = new SparkleStatusIconController(); - - private Drawing.Bitmap syncing_idle_image = SparkleUIHelpers.GetBitmap ("process-syncing-idle"); - private Drawing.Bitmap syncing_up_image = SparkleUIHelpers.GetBitmap ("process-syncing-up"); - private Drawing.Bitmap syncing_down_image = SparkleUIHelpers.GetBitmap ("process-syncing-down"); - private Drawing.Bitmap syncing_image = SparkleUIHelpers.GetBitmap ("process-syncing"); - private Drawing.Bitmap syncing_error_image = SparkleUIHelpers.GetBitmap ("process-syncing-error"); + + private readonly Drawing.Bitmap syncing_idle_image = SparkleUIHelpers.GetBitmap("process-syncing-idle"); + private readonly Drawing.Bitmap syncing_up_image = SparkleUIHelpers.GetBitmap("process-syncing-up"); + private readonly Drawing.Bitmap syncing_down_image = SparkleUIHelpers.GetBitmap("process-syncing-down"); + private readonly Drawing.Bitmap syncing_image = SparkleUIHelpers.GetBitmap("process-syncing"); + private readonly Drawing.Bitmap syncing_error_image = SparkleUIHelpers.GetBitmap("process-syncing-error"); private ContextMenu context_menu; private SparkleMenuItem log_item; private SparkleMenuItem state_item; private SparkleMenuItem exit_item; - private SparkleMenuItem [] state_menu_items; + private SparkleMenuItem[] state_menu_items; - private SparkleNotifyIcon notify_icon = new SparkleNotifyIcon (); + private readonly SparkleNotifyIcon notify_icon = new SparkleNotifyIcon(); - public SparkleStatusIcon () - { + public SparkleStatusIcon() { this.notify_icon.HeaderText = "SparkleShare"; - this.notify_icon.Icon = this.syncing_idle_image; + this.notify_icon.Icon = this.syncing_idle_image; - CreateMenu (); - - Controller.UpdateIconEvent += delegate (IconState state) { - Dispatcher.BeginInvoke ((Action) delegate { - switch (state) { - case IconState.Idle: { - this.notify_icon.Icon = this.syncing_idle_image; - break; + CreateMenu(); + + Controller.UpdateIconEvent += delegate(IconState state) { + Dispatcher.BeginInvoke( + (Action) delegate { + switch(state) { + case IconState.Idle: { + this.notify_icon.Icon = this.syncing_idle_image; + break; + } + case IconState.SyncingUp: { + this.notify_icon.Icon = this.syncing_up_image; + break; + } + case IconState.SyncingDown: { + this.notify_icon.Icon = this.syncing_down_image; + break; + } + case IconState.Syncing: { + this.notify_icon.Icon = this.syncing_image; + break; + } + case IconState.Error: { + this.notify_icon.Icon = this.syncing_error_image; + break; + } } - case IconState.SyncingUp: { - this.notify_icon.Icon = this.syncing_up_image; - break; - } - case IconState.SyncingDown: { - this.notify_icon.Icon = this.syncing_down_image; - break; - } - case IconState.Syncing: { - this.notify_icon.Icon = this.syncing_image; - break; - } - case IconState.Error: { - this.notify_icon.Icon = this.syncing_error_image; - break; - } - } - }); + }); }; - - Controller.UpdateStatusItemEvent += delegate (string state_text) { - Dispatcher.BeginInvoke ((Action) delegate { - this.state_item.Header = state_text; - this.state_item.UpdateLayout (); - if (Controller.Projects.Length == this.state_menu_items.Length) { - for (int i = 0; i < Controller.Projects.Length; i++) - this.state_menu_items [i].Header = Controller.Projects [i].StatusMessage; + Controller.UpdateStatusItemEvent += delegate(string state_text) { + Dispatcher.BeginInvoke( + (Action) delegate { + this.state_item.Header = state_text; + this.state_item.UpdateLayout(); + + if(Controller.Projects.Length == state_menu_items.Length) { + for(int i = 0; i < Controller.Projects.Length; i++) + state_menu_items[i].Header = Controller.Projects[i].StatusMessage; } this.notify_icon.HeaderText = "SparkleShare\n" + state_text; }); }; - - Controller.UpdateMenuEvent += delegate (IconState state) { - Dispatcher.BeginInvoke ((Action) delegate { - CreateMenu (); - }); + + Controller.UpdateMenuEvent += delegate { + Dispatcher.BeginInvoke((Action) CreateMenu); }; - - Controller.UpdateQuitItemEvent += delegate (bool item_enabled) { - Dispatcher.BeginInvoke ((Action) delegate { + + Controller.UpdateQuitItemEvent += delegate(bool item_enabled) { + Dispatcher.BeginInvoke((Action) delegate { this.exit_item.IsEnabled = item_enabled; - this.exit_item.UpdateLayout (); + this.exit_item.UpdateLayout(); }); }; } - public void CreateMenu () - { - this.context_menu = new ContextMenu (); + public void CreateMenu() { + this.context_menu = new ContextMenu(); - this.state_item = new SparkleMenuItem () { - Header = Controller.StateText, + this.state_item = new SparkleMenuItem { + Header = Controller.StateText, IsEnabled = false }; - - Image folder_image = new Image () { - Source = SparkleUIHelpers.GetImageSource ("sparkleshare-folder"), - Width = 16, + + Image folder_image = new Image { + Source = SparkleUIHelpers.GetImageSource("sparkleshare-folder"), + Width = 16, Height = 16 }; - - SparkleMenuItem folder_item = new SparkleMenuItem () { + + SparkleMenuItem folder_item = new SparkleMenuItem { Header = "SparkleShare", - Icon = folder_image + Icon = folder_image }; - - SparkleMenuItem add_item = new SparkleMenuItem () { Header = "Add hosted project…" }; - - this.log_item = new SparkleMenuItem () { - Header = "Recent changes…", + + SparkleMenuItem add_item = new SparkleMenuItem { + Header = "Add hosted project…" + }; + + this.log_item = new SparkleMenuItem { + Header = "Recent changes…", IsEnabled = Controller.RecentEventsItemEnabled }; - SparkleMenuItem link_code_item = new SparkleMenuItem () { Header = "Client ID" }; - - if (Controller.LinkCodeItemEnabled) { - SparkleMenuItem code_item = new SparkleMenuItem (); - code_item.Header = Program.Controller.CurrentUser.PublicKey.Substring (0, 20) + "..."; - - SparkleMenuItem copy_item = new SparkleMenuItem () { Header = "Copy to Clipboard" }; - copy_item.Click += delegate { Controller.CopyToClipboardClicked (); }; - - link_code_item.Items.Add (code_item); - link_code_item.Items.Add (new Separator()); - link_code_item.Items.Add (copy_item); + SparkleMenuItem link_code_item = new SparkleMenuItem { + Header = "Client ID" + }; + + if(Controller.LinkCodeItemEnabled) { + SparkleMenuItem code_item = new SparkleMenuItem { + Header = Program.Controller.CurrentUser.PublicKey.Substring(0, 20) + "..." + }; + + SparkleMenuItem copy_item = new SparkleMenuItem { + Header = "Copy to Clipboard" + }; + copy_item.Click += delegate { + Controller.CopyToClipboardClicked(); + }; + + link_code_item.Items.Add(code_item); + link_code_item.Items.Add(new Separator()); + link_code_item.Items.Add(copy_item); } - CheckBox notify_check_box = new CheckBox () { - Margin = new Thickness (6, 0, 0, 0), + CheckBox notify_check_box = new CheckBox { + Margin = new Thickness(6, 0, 0, 0), IsChecked = Program.Controller.NotificationsEnabled }; - - SparkleMenuItem notify_item = new SparkleMenuItem () { Header = "Notifications" }; - notify_item.Icon = notify_check_box; - SparkleMenuItem about_item = new SparkleMenuItem () { Header = "About SparkleShare" }; - this.exit_item = new SparkleMenuItem () { Header = "Exit" }; - - - add_item.Click += delegate { Controller.AddHostedProjectClicked (); }; - this.log_item.Click += delegate { Controller.RecentEventsClicked (); }; - about_item.Click += delegate { Controller.AboutClicked (); }; - + SparkleMenuItem notify_item = new SparkleMenuItem { + Header = "Notifications", + Icon = notify_check_box + }; + + SparkleMenuItem about_item = new SparkleMenuItem { + Header = "About SparkleShare" + }; + this.exit_item = new SparkleMenuItem { + Header = "Exit" + }; + + + add_item.Click += delegate { + Controller.AddHostedProjectClicked(); + }; + this.log_item.Click += delegate { + Controller.RecentEventsClicked(); + }; + about_item.Click += delegate { + Controller.AboutClicked(); + }; + notify_check_box.Click += delegate { this.context_menu.IsOpen = false; - Program.Controller.ToggleNotifications (); + Program.Controller.ToggleNotifications(); notify_check_box.IsChecked = Program.Controller.NotificationsEnabled; }; - + notify_item.Click += delegate { - Program.Controller.ToggleNotifications (); + Program.Controller.ToggleNotifications(); notify_check_box.IsChecked = Program.Controller.NotificationsEnabled; }; - + this.exit_item.Click += delegate { - this.notify_icon.Dispose (); - Controller.QuitClicked (); + this.notify_icon.Dispose(); + Controller.QuitClicked(); }; - - - this.context_menu.Items.Add (this.state_item); - this.context_menu.Items.Add (new Separator ()); - this.context_menu.Items.Add (folder_item); - this.state_menu_items = new SparkleMenuItem [Controller.Projects.Length]; - // FIXME Add event handlers for pausing - if (Controller.Projects.Length > 0) { + this.context_menu.Items.Add(this.state_item); + this.context_menu.Items.Add(new Separator()); + this.context_menu.Items.Add(folder_item); + + state_menu_items = new SparkleMenuItem[Controller.Projects.Length]; + + if(Controller.Projects.Length > 0) { int i = 0; - foreach (ProjectInfo project in Controller.Projects) { - SparkleMenuItem item = new SparkleMenuItem () { - Header = project.Name.Replace ("_", "__") + foreach(ProjectInfo project in Controller.Projects) { + + SparkleMenuItem subfolder_item = new SparkleMenuItem { + Header = project.Name.Replace("_", "__"), + Icon = new Image { + Source = SparkleUIHelpers.GetImageSource("folder"), + Width = 16, + Height = 16 + } }; - item.Icon = new Image () { - Source = SparkleUIHelpers.GetImageSource ("folder"), - Width = 16, - Height = 16 - }; - - this.state_menu_items [i] = new SparkleMenuItem () { + state_menu_items[i] = new SparkleMenuItem { Header = project.StatusMessage, IsEnabled = false }; - item.Items.Add (this.state_menu_items [i]); - item.Items.Add (new Separator ()); + subfolder_item.Items.Add(state_menu_items[i]); + subfolder_item.Items.Add(new Separator()); - if (project.IsPaused) { + if(project.IsPaused) { SparkleMenuItem resume_item; - - if (project.UnsyncedChangesInfo.Count > 0) { - foreach (KeyValuePair pair in project.UnsyncedChangesInfo) - item.Items.Add (new SparkleMenuItem () { + + if(project.UnsyncedChangesInfo.Count > 0) { + foreach(KeyValuePair pair in project.UnsyncedChangesInfo) + subfolder_item.Items.Add(new SparkleMenuItem { Header = pair.Key, // TODO image IsEnabled = false }); - if (!string.IsNullOrEmpty (project.MoreUnsyncedChanges)) { - item.Items.Add (new SparkleMenuItem () { + if(!string.IsNullOrEmpty(project.MoreUnsyncedChanges)) { + subfolder_item.Items.Add(new SparkleMenuItem { Header = project.MoreUnsyncedChanges, IsEnabled = false }); } - - item.Items.Add (new Separator ()); - resume_item = new SparkleMenuItem () { Header = "Sync and Resume…" }; - - } else { - resume_item = new SparkleMenuItem () { Header = "Resume" }; - } - - //resume_item.Click += Controller.ResumeDelegate (project.Name); - item.Items.Add (resume_item); - } else { - if (Controller.Projects [i].HasError) { - item.Icon = new Image () { - Source = (BitmapSource) Imaging.CreateBitmapSourceFromHIcon ( - System.Drawing.SystemIcons.Exclamation.Handle, Int32Rect.Empty, - BitmapSizeOptions.FromWidthAndHeight (16,16)) + subfolder_item.Items.Add(new Separator()); + resume_item = new SparkleMenuItem { + Header = "Sync and Resume…" }; - SparkleMenuItem try_again_item = new SparkleMenuItem () { Header = "Try Again" }; - //try_again_item.Click += Controller.TryAgainDelegate (project.Name); - item.Items.Add (try_again_item); - } else { - SparkleMenuItem pause_item = new SparkleMenuItem () { Header = "Pause" }; - //pause_item.Click += Controller.PauseDelegate (project.Name); - item.Items.Add (pause_item); + resume_item = new SparkleMenuItem { + Header = "Resume" + }; + } + + resume_item.Click += (sender, e) => Controller.ResumeDelegate(project.Name)(sender, e); + subfolder_item.Items.Add(resume_item); + + } else { + if(Controller.Projects[i].HasError) { + subfolder_item.Icon = new Image { + Source = Imaging.CreateBitmapSourceFromHIcon( + Drawing.SystemIcons.Exclamation.Handle, Int32Rect.Empty, + BitmapSizeOptions.FromWidthAndHeight(16, 16)) + }; + + SparkleMenuItem try_again_item = new SparkleMenuItem { + Header = "Try Again" + }; + try_again_item.Click += (sender, e) => Controller.TryAgainDelegate(project.Name)(sender, e); + subfolder_item.Items.Add(try_again_item); + + } else { + SparkleMenuItem pause_item = new SparkleMenuItem { + Header = "Pause" + }; + pause_item.Click += + (sender, e) => Controller.PauseDelegate(project.Name)(sender, e); + subfolder_item.Items.Add(pause_item); } } - - this.context_menu.Items.Add (item); + + this.context_menu.Items.Add(subfolder_item); i++; }; } + folder_item.Items.Add(this.log_item); + folder_item.Items.Add(add_item); + folder_item.Items.Add(new Separator()); + folder_item.Items.Add(notify_item); + folder_item.Items.Add(new Separator()); + folder_item.Items.Add(link_code_item); + folder_item.Items.Add(new Separator()); + folder_item.Items.Add(about_item); - folder_item.Items.Add (this.log_item); - folder_item.Items.Add (add_item); - folder_item.Items.Add (new Separator ()); - folder_item.Items.Add (notify_item); - folder_item.Items.Add (new Separator ()); - folder_item.Items.Add (link_code_item); - folder_item.Items.Add (new Separator ()); - folder_item.Items.Add (about_item); + this.context_menu.Items.Add(new Separator()); + this.context_menu.Items.Add(this.exit_item); - this.context_menu.Items.Add (new Separator ()); - this.context_menu.Items.Add (this.exit_item); - this.notify_icon.ContextMenu = this.context_menu; } - - public void ShowBalloon (string title, string subtext, string image_path) - { - this.notify_icon.ShowBalloonTip (title, subtext, image_path); - } - - public void Dispose () - { - this.notify_icon.Dispose (); + public void ShowBalloon(string title, string subtext, string image_path) { + this.notify_icon.ShowBalloonTip(title, subtext, image_path); + } + + + public void Dispose() { + this.notify_icon.Dispose(); } } - - + public class SparkleMenuItem : MenuItem { - - public SparkleMenuItem () : base () - { - Padding = new Thickness (6, 3, 4, 0); + + public SparkleMenuItem() { + Padding = new Thickness(6, 3, 4, 0); } } }