[tasque] [tasque] Outsource tray logic from Application.cs



commit 2fd20476cd3a575e20bbce7a7dfed0ad7828c0a5
Author: Antonius Riha <antoniusriha gmail com>
Date:   Wed Aug 22 15:48:14 2012 +0200

    [tasque] Outsource tray logic from Application.cs
    
    Added:
    	* StatusIconTray.cs: Represents a systray icon using Gtk.StatusIcon class
    	* GtkTray.cs: Abstract base class for all Gtk based systray icons.
    
    Note: The two classes structure has been chosen in order to support the
    future implementation of an (Ubuntu/Unity-) AppIndicator as systray, which
    will use GtkTray as base class.

 src/Application.cs    |  284 ++++++++----------------------------------------
 src/GtkTray.cs        |  221 ++++++++++++++++++++++++++++++++++++++
 src/Makefile.am       |    2 +
 src/StatusIconTray.cs |   51 +++++++++
 tasque.csproj         |    2 +
 5 files changed, 324 insertions(+), 236 deletions(-)
---
diff --git a/src/Application.cs b/src/Application.cs
index f5aee20..5d5ed84 100644
--- a/src/Application.cs
+++ b/src/Application.cs
@@ -57,11 +57,10 @@ namespace Tasque
 #endif
 		private Gdk.Pixbuf normalPixBuf;
 		private Gtk.Image trayImage;
-		private Gtk.StatusIcon trayIcon;	
+		private GtkTray trayIcon;
 		private Preferences preferences;
 		private EventBox eb;
 		private IBackend backend;
-		private TaskGroupModel overdue_tasks, today_tasks, tomorrow_tasks;
 		private PreferencesDialog preferencesDialog;
 		private bool quietStart = false;
 		
@@ -75,22 +74,6 @@ namespace Tasque
 		
 		private IBackend customBackend;
 
-		private UIManager uiManager;
-		private const string menuXml = @"
-<ui>
-	<popup name=""TrayIconMenu"">
-		<menuitem action=""NewTaskAction""/>
-		<separator/>
-		<menuitem action=""PreferencesAction""/>
-		<menuitem action=""AboutAction""/>
-		<separator/>
-		<menuitem action=""RefreshAction""/>
-		<separator/>
-		<menuitem action=""QuitAction""/>
-	</popup>
-</ui>
-";
-
 		public static IBackend Backend
 		{ 
 			get { return Application.Instance.backend; }
@@ -127,16 +110,20 @@ namespace Tasque
 			}
 		}
 
-		public UIManager UIManager
-		{
-			get { return uiManager; }
-		}
+		public event EventHandler BackendChanged;
 
-		public StatusIcon Tray
+		void OnBackendChanged ()
 		{
-			get { return trayIcon; }
+			if (BackendChanged != null)
+				BackendChanged (this, EventArgs.Empty);
 		}
-
+		
+		public TaskGroupModel OverdueTasks { get; private set; }
+		
+		public TaskGroupModel TodayTasks { get; private set; }
+		
+		public TaskGroupModel TomorrowTasks { get; private set; }
+		
 		public static Preferences Preferences
 		{
 			get { return Application.Instance.preferences; }
@@ -166,8 +153,6 @@ namespace Tasque
 				"Tasque",
 				"Tasque",
 				args);
-			
-			RegisterUIManager ();
 
 			preferences = new Preferences (nativeApp.ConfDir);
 			
@@ -354,9 +339,11 @@ namespace Tasque
 			}
 				
 			// Initialize the new backend
+			var oldBackend = backend;
 			this.backend = value;
 			if (this.backend == null) {
-				RefreshTrayIconTooltip ();
+				if (trayIcon != null)
+					trayIcon.RefreshTrayIconTooltip ();
 				return;
 			}
 				
@@ -372,10 +359,14 @@ namespace Tasque
 			}
 
 			RebuildTooltipTaskGroupModels ();
-			RefreshTrayIconTooltip ();
+			if (trayIcon != null)
+				trayIcon.RefreshTrayIconTooltip ();
 			
 			Logger.Debug("Configuration status: {0}",
 			             this.backend.Configured.ToString());
+
+			if (backend != oldBackend)
+				OnBackendChanged ();
 		}
 
 		private bool InitializeIdle()
@@ -394,7 +385,7 @@ namespace Tasque
 				}
 			}
 			
-			SetupTrayIcon ();
+			trayIcon = GtkTray.CreateTray ();
 			
 			if (backend == null) {
 				// Pop open the preferences dialog so the user can choose a
@@ -438,30 +429,16 @@ namespace Tasque
 				
 				UnhookFromTooltipTaskGroupModels ();
 				RebuildTooltipTaskGroupModels ();
-				RefreshTrayIconTooltip ();
+				if (trayIcon != null)
+					trayIcon.RefreshTrayIconTooltip ();
 			}
 			
 			return true;
 		}
 
-		private void SetupTrayIcon ()
-		{
-			trayIcon = new Gtk.StatusIcon();
-			trayIcon.Pixbuf = Utilities.GetIcon ("tasque-24", 24);
-			
-			// hooking event
-			trayIcon.Activate += OnTrayIconClick;
-			trayIcon.PopupMenu += OnTrayIconPopupMenu;
-
-			// showing the trayicon
-			trayIcon.Visible = true;
-
-			RefreshTrayIconTooltip ();
-		}
-
 		private void UnhookFromTooltipTaskGroupModels ()
 		{
-			foreach (TaskGroupModel model in new TaskGroupModel[] { overdue_tasks, today_tasks, tomorrow_tasks })
+			foreach (TaskGroupModel model in new TaskGroupModel[] { OverdueTasks, TodayTasks, TomorrowTasks })
 			{
 				if (model == null) {
 					continue;
@@ -475,24 +452,25 @@ namespace Tasque
 
 		private void OnTooltipModelChanged (object o, EventArgs args)
 		{
-			RefreshTrayIconTooltip ();
+			if (trayIcon != null)
+				trayIcon.RefreshTrayIconTooltip ();
 		}
 
 		private void RebuildTooltipTaskGroupModels ()
 		{
 			if (backend == null || backend.Tasks == null) {
-				overdue_tasks = null;
-				today_tasks = null;
-				tomorrow_tasks = null;
+				OverdueTasks = null;
+				TodayTasks = null;
+				TomorrowTasks = null;
 				
 				return;
 			}
 
-			overdue_tasks = TaskGroupModelFactory.CreateOverdueModel (backend.Tasks);
-			today_tasks = TaskGroupModelFactory.CreateTodayModel (backend.Tasks);
-			tomorrow_tasks = TaskGroupModelFactory.CreateTomorrowModel (backend.Tasks);
+			OverdueTasks = TaskGroupModelFactory.CreateOverdueModel (backend.Tasks);
+			TodayTasks = TaskGroupModelFactory.CreateTodayModel (backend.Tasks);
+			TomorrowTasks = TaskGroupModelFactory.CreateTomorrowModel (backend.Tasks);
 
-			foreach (TaskGroupModel model in new TaskGroupModel[] { overdue_tasks, today_tasks, tomorrow_tasks })
+			foreach (TaskGroupModel model in new TaskGroupModel[] { OverdueTasks, TodayTasks, TomorrowTasks })
 			{
 				if (model == null) {
 					continue;
@@ -504,153 +482,23 @@ namespace Tasque
 			}
 		}
 		
-		private void RefreshTrayIconTooltip ()
-		{
-			if (trayIcon == null) {
-				return;
-			}
-
-			StringBuilder sb = new StringBuilder ();
-			if (overdue_tasks != null) {
-				int count =  overdue_tasks.IterNChildren ();
-
-				if (count > 0) {
-					sb.Append (String.Format (Catalog.GetPluralString ("{0} task is Overdue\n", "{0} tasks are Overdue\n", count), count));
-				}
-			}
-			
-			if (today_tasks != null) {
-				int count =  today_tasks.IterNChildren ();
-
-				if (count > 0) {
-					sb.Append (String.Format (Catalog.GetPluralString ("{0} task for Today\n", "{0} tasks for Today\n", count), count));
-				}
-			}
-
-			if (tomorrow_tasks != null) {
-				int count =  tomorrow_tasks.IterNChildren ();
-
-				if (count > 0) {
-					sb.Append (String.Format (Catalog.GetPluralString ("{0} task for Tomorrow\n", "{0} tasks for Tomorrow\n", count), count));
-				}
-			}
-
-			if (sb.Length == 0) {
-				// Translators: This is the status icon's tooltip. When no tasks are overdue, due today, or due tomorrow, it displays this fun message
-				trayIcon.Tooltip = Catalog.GetString ("Tasque Rocks");
-				return;
-			}
-
-			trayIcon.Tooltip = sb.ToString ().TrimEnd ('\n');
-		}
-
-
-		private void OnPreferences (object sender, EventArgs args)
-		{
-			Logger.Info ("OnPreferences called");
-			if (preferencesDialog == null) {
-				preferencesDialog = new PreferencesDialog ();
-				preferencesDialog.Hidden += OnPreferencesDialogHidden;
-			}
-			
-			preferencesDialog.Present ();
-		}
-		
 		private void OnPreferencesDialogHidden (object sender, EventArgs args)
 		{
 			preferencesDialog.Destroy ();
 			preferencesDialog = null;
 		}
 		
-		public static void ShowPreferences()
-		{
-			application.OnPreferences(null, EventArgs.Empty);
-		}
-
-		private void OnAbout (object sender, EventArgs args)
-		{
-			string [] authors = new string [] {
-				"Boyd Timothy <btimothy gmail com>",
-				"Calvin Gaisford <calvinrg gmail com>",
-				"Sandy Armstrong <sanfordarmstrong gmail com>",
-				"Brian G. Merrell <bgmerrell novell com>"
-			};
-
-			/* string [] documenters = new string [] {
-			   "Calvin Gaisford <calvinrg gmail com>"
-			   };
-			   */
-
-			string translators = Catalog.GetString ("translator-credits");
-			if (translators == "translator-credits")
-				translators = null;
-			
-			Gtk.AboutDialog about = new Gtk.AboutDialog ();
-			about.Name = "Tasque";
-			about.Version = Defines.Version;
-			about.Logo = Utilities.GetIcon("tasque-48", 48);
-			about.Copyright =
-				Catalog.GetString ("Copyright \xa9 2008 Novell, Inc.");
-			about.Comments = Catalog.GetString ("A Useful Task List");
-			about.Website = "http://live.gnome.org/Tasque";;
-			about.WebsiteLabel = Catalog.GetString("Tasque Project Homepage");
-			about.Authors = authors;
-			//about.Documenters = documenters;
-			about.TranslatorCredits = translators;
-			about.IconName = "tasque";
-			about.SetSizeRequest(300, 300);
-			about.Run ();
-			about.Destroy ();
-
-		}
-
-
-		private void OnShowTaskWindow (object sender, EventArgs args)
-		{
-			TaskWindow.ShowWindow();
-		}
-		
-		private void OnNewTask (object sender, EventArgs args)
-		{
-			// Show the TaskWindow and then cause a new task to be created
-			TaskWindow.ShowWindow ();
-			TaskWindow.GrabNewTaskEntryFocus ();
-		}
-
-		private void OnQuit (object sender, EventArgs args)
+		public static void ShowPreferences ()
 		{
-			Logger.Info ("OnQuit called - terminating application");
-			if (backend != null) {
-				UnhookFromTooltipTaskGroupModels ();
-				backend.Cleanup();
+			Logger.Info ("ShowPreferences called");
+			var app = application;
+			if (app.preferencesDialog == null) {
+				app.preferencesDialog = new PreferencesDialog ();
+				app.preferencesDialog.Hidden += app.OnPreferencesDialogHidden;
 			}
-			TaskWindow.SavePosition();
-
-			nativeApp.QuitMainLoop ();
-		}
-		
-		private void OnRefreshAction (object sender, EventArgs args)
-		{
-			Application.Backend.Refresh();
-		}
-
-		private void OnTrayIconClick (object sender, EventArgs args) // handler for mouse click
-		{
-			TaskWindow.ToggleWindowVisible ();
-		}
-
-		private void OnTrayIconPopupMenu (object sender, EventArgs args)
-		{
-			Menu popupMenu = (Menu) uiManager.GetWidget ("/TrayIconMenu");
-
-			bool backendItemsSensitive = (backend != null && backend.Initialized);
 			
-			uiManager.GetAction ("/TrayIconMenu/NewTaskAction").Sensitive = backendItemsSensitive;
-			uiManager.GetAction ("/TrayIconMenu/RefreshAction").Sensitive = backendItemsSensitive;
-
-			popupMenu.ShowAll(); // shows everything
-			popupMenu.Popup();
-		}		
+			app.preferencesDialog.Present ();
+		}
 
 		public static void Main(string[] args)
 		{
@@ -698,50 +546,14 @@ namespace Tasque
 
 		public void Quit ()
 		{
-			OnQuit (null, null);
-		}
-
-		private void RegisterUIManager ()
-		{
-			ActionGroup trayActionGroup = new ActionGroup ("Tray");
-			trayActionGroup.Add (new ActionEntry [] {
-				new ActionEntry ("NewTaskAction",
-				                 Stock.New,
-				                 Catalog.GetString ("New Task ..."),
-				                 null,
-				                 null,
-				                 OnNewTask),
-				
-				new ActionEntry ("ShowTasksAction",
-				                 null,
-				                 Catalog.GetString ("Show Tasks ..."),
-				                 null,
-				                 null,
-				                 OnShowTaskWindow),
+			Logger.Info ("Quit called - terminating application");
+			if (backend != null) {
+				UnhookFromTooltipTaskGroupModels ();
+				backend.Cleanup ();
+			}
+			TaskWindow.SavePosition ();
 
-				new ActionEntry ("AboutAction",
-				                 Stock.About,
-				                 OnAbout),
-				
-				new ActionEntry ("PreferencesAction",
-				                 Stock.Preferences,
-				                 OnPreferences),
-				
-				new ActionEntry ("RefreshAction",
-				                 Stock.Execute,
-				                 Catalog.GetString ("Refresh Tasks ..."),
-				                 null,
-				                 null,
-				                 OnRefreshAction),
-				
-				new ActionEntry ("QuitAction",
-				                 Stock.Quit,
-				                 OnQuit)
-			});
-			
-			uiManager = new UIManager ();
-			uiManager.AddUiFromString (menuXml);
-			uiManager.InsertActionGroup (trayActionGroup, 0);
+			nativeApp.QuitMainLoop ();
 		}
 	}
 }
diff --git a/src/GtkTray.cs b/src/GtkTray.cs
new file mode 100644
index 0000000..9d7a596
--- /dev/null
+++ b/src/GtkTray.cs
@@ -0,0 +1,221 @@
+// 
+// GtkTray.cs
+//  
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+// 
+// Copyright (c) 2012 Antonius Riha
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Text;
+using Mono.Unix;
+using Gtk;
+using Tasque.Backends;
+
+namespace Tasque
+{
+	public abstract class GtkTray : IDisposable
+	{
+		public static GtkTray CreateTray ()
+		{
+			return new StatusIconTray ();
+		}
+
+		protected GtkTray ()
+		{
+			UpdateBackend ();
+			Application.Instance.BackendChanged += HandleBackendChanged;
+			RefreshTrayIconTooltip ();
+		}
+
+		#region IDisposable implementation
+		public void Dispose ()
+		{
+			var app = Application.Instance;
+			if (app != null)
+				app.BackendChanged -= HandleBackendChanged;
+		}
+		#endregion
+		
+		public void RefreshTrayIconTooltip ()
+		{
+			var sb = new StringBuilder ();
+			var overdueTasks = Application.Instance.OverdueTasks;
+			if (overdueTasks != null) {
+				int count = overdueTasks.IterNChildren ();
+
+				if (count > 0) {
+					sb.Append (String.Format (Catalog.GetPluralString ("{0} task is Overdue\n", "{0} tasks are Overdue\n", count), count));
+				}
+			}
+			
+			var todayTasks = Application.Instance.TodayTasks;
+			if (todayTasks != null) {
+				int count = todayTasks.IterNChildren ();
+
+				if (count > 0) {
+					sb.Append (String.Format (Catalog.GetPluralString ("{0} task for Today\n", "{0} tasks for Today\n", count), count));
+				}
+			}
+			
+			var tomorrowTasks = Application.Instance.TomorrowTasks;
+			if (tomorrowTasks != null) {
+				int count = tomorrowTasks.IterNChildren ();
+
+				if (count > 0) {
+					sb.Append (String.Format (Catalog.GetPluralString ("{0} task for Tomorrow\n", "{0} tasks for Tomorrow\n", count), count));
+				}
+			}
+
+			if (sb.Length == 0) {
+				// Translators: This is the status icon's tooltip. When no tasks are overdue, due today, or due tomorrow, it displays this fun message
+				Tooltip = Catalog.GetString ("Tasque Rocks");
+				return;
+			}
+
+			Tooltip = sb.ToString ().TrimEnd ('\n');
+		}
+
+		protected string IconName { get { return "tasque-24"; } }
+		
+		protected Menu Menu {
+			get {
+				if (uiManager == null)
+					RegisterUIManager ();
+				return (Menu)uiManager.GetWidget ("/TrayIconMenu");
+			}
+		}
+		
+		protected Gtk.Action ToggleTaskWindowAction { get; private set; }
+
+		protected string Tooltip { get; private set; }
+		
+		protected virtual void OnTooltipChanged () {}
+		
+		void HandleBackendChanged (object sender, EventArgs e)
+		{
+			UpdateBackend ();
+		}
+
+		void HandleBackendInitialized ()
+		{
+			UpdateActionSensitivity ();
+		}
+
+		void OnAbout (object sender, EventArgs args)
+		{
+			var authors = new string [] {
+				"Boyd Timothy <btimothy gmail com>",
+				"Calvin Gaisford <calvinrg gmail com>",
+				"Sandy Armstrong <sanfordarmstrong gmail com>",
+				"Brian G. Merrell <bgmerrell novell com>"
+			};
+			
+			var translators = Catalog.GetString ("translator-credits");
+			if (translators == "translator-credits")
+				translators = null;
+			
+			var about = new AboutDialog ();
+			about.ProgramName = "Tasque";
+			about.Version = Defines.Version;
+			about.Logo = Utilities.GetIcon("tasque-48", 48);
+			about.Copyright = Catalog.GetString ("Copyright \xa9 2008 Novell, Inc.");
+			about.Comments = Catalog.GetString ("A Useful Task List");
+			about.Website = "http://live.gnome.org/Tasque";;
+			about.WebsiteLabel = Catalog.GetString("Tasque Project Homepage");
+			about.Authors = authors;
+			about.TranslatorCredits = translators;
+			about.IconName = "tasque";
+			about.SetSizeRequest(300, 300);
+			about.Run ();
+			about.Destroy ();
+		}
+
+		void RegisterUIManager ()
+		{
+			var trayActionGroup = new ActionGroup ("Tray");
+			trayActionGroup.Add (new ActionEntry [] {
+				new ActionEntry ("NewTaskAction", Stock.New, Catalog.GetString ("New Task ..."), null, null, delegate {
+					// Show the TaskWindow and then cause a new task to be created
+					TaskWindow.ShowWindow ();
+					TaskWindow.GrabNewTaskEntryFocus ();
+				}),
+
+				new ActionEntry ("AboutAction", Stock.About, OnAbout),
+
+				new ActionEntry ("PreferencesAction", Stock.Preferences, delegate { Application.ShowPreferences (); }),
+
+				new ActionEntry ("RefreshAction", Stock.Execute, Catalog.GetString ("Refresh Tasks ..."),
+				                 null, null, delegate { Application.Backend.Refresh(); }),
+
+				new ActionEntry ("QuitAction", Stock.Quit, delegate { Application.Instance.Quit (); })
+			});
+			
+			ToggleTaskWindowAction = new Gtk.Action ("ToggleTaskWindowAction", "Toggle Task Window");
+			ToggleTaskWindowAction.ActionGroup = trayActionGroup;
+			ToggleTaskWindowAction.Activated += delegate { TaskWindow.ToggleWindowVisible (); };
+			
+			uiManager = new UIManager ();
+			uiManager.AddUiFromString (MenuXml);
+			uiManager.InsertActionGroup (trayActionGroup, 0);
+		}
+
+		void UpdateActionSensitivity ()
+		{
+			var backend = Application.Backend;
+			var backendItemsSensitive = (backend != null && backend.Initialized);
+			
+			if (uiManager == null)
+				RegisterUIManager ();
+			
+			uiManager.GetAction ("/TrayIconMenu/NewTaskAction").Sensitive = backendItemsSensitive;
+			uiManager.GetAction ("/TrayIconMenu/RefreshAction").Sensitive = backendItemsSensitive;
+		}
+
+		void UpdateBackend ()
+		{
+			if (backend != null)
+				backend.BackendInitialized -= HandleBackendInitialized;
+			backend = Application.Backend;
+
+			if (backend != null)
+				backend.BackendInitialized += HandleBackendInitialized;
+
+			UpdateActionSensitivity ();
+		}
+
+		IBackend backend;
+		UIManager uiManager;
+		const string MenuXml = @"
+<ui>
+	<popup name=""TrayIconMenu"">
+		<menuitem action=""NewTaskAction""/>
+		<separator/>
+		<menuitem action=""PreferencesAction""/>
+		<menuitem action=""AboutAction""/>
+		<separator/>
+		<menuitem action=""RefreshAction""/>
+		<separator/>
+		<menuitem action=""QuitAction""/>
+	</popup>
+</ui>
+";
+	}
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index b5569e1..7e47f0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,6 +66,7 @@ CSFILES = \
 	$(srcdir)/CompletedTaskGroup.cs \
 	$(srcdir)/DateButton.cs \
 	$(srcdir)/GtkApplication.cs \
+	$(srcdir)/GtkTray.cs \
 	$(srcdir)/GnomeApplication.cs \
 	$(srcdir)/Logger.cs \
 	$(srcdir)/NoteDialog.cs \
@@ -74,6 +75,7 @@ CSFILES = \
 	$(srcdir)/PreferencesDialog.cs \
 	$(srcdir)/RemoteControl.cs \
 	$(srcdir)/RemoteControlProxy.cs \
+	$(srcdir)/StatusIconTray.cs \
 	$(srcdir)/TaskCalendar.cs \
 	$(srcdir)/TaskGroupModel.cs \
 	$(srcdir)/CompletedTaskGroupModel.cs \
diff --git a/src/StatusIconTray.cs b/src/StatusIconTray.cs
new file mode 100644
index 0000000..b056b17
--- /dev/null
+++ b/src/StatusIconTray.cs
@@ -0,0 +1,51 @@
+// 
+// StatusIconTray.cs
+//  
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+// 
+// Copyright (c) 2012 Antonius Riha
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using Gtk;
+
+namespace Tasque
+{
+	public class StatusIconTray : GtkTray
+	{
+		public StatusIconTray ()
+		{
+			tray = new StatusIcon (Utilities.GetIcon (IconName, 24));
+			tray.Visible = true;
+			tray.Activate += delegate { ToggleTaskWindowAction.Activate (); };
+			tray.PopupMenu += (sender, e) => {
+				var popupMenu = Menu;
+				popupMenu.ShowAll (); // shows everything
+				tray.PresentMenu (popupMenu, (uint)e.Args [0], (uint)e.Args [1]);
+			};
+		}
+		
+		protected override void OnTooltipChanged ()
+		{
+			tray.Tooltip = Tooltip;
+		}
+		
+		StatusIcon tray;
+	}
+}
diff --git a/tasque.csproj b/tasque.csproj
index aa9d46e..098f7c0 100644
--- a/tasque.csproj
+++ b/tasque.csproj
@@ -66,6 +66,8 @@
     <None Include="data\images\tasque.svg" />
     <None Include="src\Tasque.exe.config.in" />
     <Compile Include="src\Defines.cs" />
+    <Compile Include="src\GtkTray.cs" />
+    <Compile Include="src\StatusIconTray.cs" />
   </ItemGroup>
   <ItemGroup>
     <Content Include="data\images\clock-16-0.png" />



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]