diff options
| author | MichaelTheShifter <[email protected]> | 2016-07-20 09:40:36 -0400 |
|---|---|---|
| committer | MichaelTheShifter <[email protected]> | 2016-07-20 09:40:36 -0400 |
| commit | d40fed5ce2bc806a91245adb18039634eac13ed0 (patch) | |
| tree | f1d7168aee6db109ac2c738ad18c9db667a6ba69 /source/ShiftUI/Widgets/NotifyIcon.cs | |
| parent | f1856e8ed30ed882229fd3fa2a4038122a5fb441 (diff) | |
| download | shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.tar.gz shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.tar.bz2 shiftos-c--d40fed5ce2bc806a91245adb18039634eac13ed0.zip | |
Move ShiftUI source code to ShiftOS
This'll be a lot easier to work on.
Diffstat (limited to 'source/ShiftUI/Widgets/NotifyIcon.cs')
| -rw-r--r-- | source/ShiftUI/Widgets/NotifyIcon.cs | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/source/ShiftUI/Widgets/NotifyIcon.cs b/source/ShiftUI/Widgets/NotifyIcon.cs new file mode 100644 index 0000000..c30006a --- /dev/null +++ b/source/ShiftUI/Widgets/NotifyIcon.cs @@ -0,0 +1,753 @@ +// 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. +// +// Copyright (c) 2005 Novell, Inc. (http://www.novell.com) +// +// Authors: +// Peter Bartok [email protected] +// +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Drawing.Text; + +namespace ShiftUI { + [DefaultProperty("Text")] + [DefaultEvent("MouseDoubleClick")] + //[Designer ("ShiftUI.Design.NotifyIconDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] + [ToolboxItemFilter("ShiftUI", ToolboxItemFilterType.Allow)] + public sealed class NotifyIcon : Component { + #region Local Variables + private Icon icon; + private Bitmap icon_bitmap; + private string text; + private bool visible; + private NotifyIconWindow window; + private bool systray_active; + private ToolTip tooltip; + private bool double_click; + private string balloon_text; + private string balloon_title; + private ToolTipIcon balloon_icon; + private ContextMenuStrip context_menu_strip; + private object tag; + #endregion // Local Variables + + #region NotifyIconWindow Class + internal class NotifyIconWindow : Form { + NotifyIcon owner; + Rectangle rect; + + public NotifyIconWindow(NotifyIcon owner) { + this.owner = owner; + is_visible = false; + rect = new Rectangle(0, 0, 1, 1); + + FormBorderStyle = FormBorderStyle.None; + + //CreateControl(); + + SizeChanged += new EventHandler(HandleSizeChanged); + + // Events that need to be sent to our parent + DoubleClick += new EventHandler(HandleDoubleClick); + MouseDown +=new MouseEventHandler(HandleMouseDown); + MouseUp +=new MouseEventHandler(HandleMouseUp); + MouseMove +=new MouseEventHandler(HandleMouseMove); + ContextMenuStrip = owner.context_menu_strip; + } + + protected override CreateParams CreateParams { + get { + CreateParams cp; + + cp = base.CreateParams; + + cp.Parent = IntPtr.Zero; + cp.Style = (int)WindowStyles.WS_POPUP; + cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS; + + cp.ExStyle = (int)(WindowExStyles.WS_EX_TOOLWINDOW); + + return cp; + } + } + + protected override void WndProc(ref Message m) { + switch((Msg)m.Msg) { + // + // NotifyIcon does CONTEXTMENU on mouse up, not down + // so we swallow the message here, and handle it on our own + // + case Msg.WM_CONTEXTMENU: + return; + + case Msg.WM_USER: { + switch ((Msg)m.LParam.ToInt32()) { + case Msg.WM_LBUTTONDOWN: { + owner.OnMouseDown (new MouseEventArgs(MouseButtons.Left, 1, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + return; + } + + case Msg.WM_LBUTTONUP: { + owner.OnMouseUp (new MouseEventArgs(MouseButtons.Left, 1, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + return; + } + + case Msg.WM_LBUTTONDBLCLK: { + owner.OnDoubleClick (EventArgs.Empty); + owner.OnMouseDoubleClick (new MouseEventArgs (MouseButtons.Left, 2, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + return; + } + + case Msg.WM_MOUSEMOVE: { + owner.OnMouseMove (new MouseEventArgs(MouseButtons.None, 1, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + return; + } + + case Msg.WM_RBUTTONDOWN: { + owner.OnMouseDown (new MouseEventArgs(MouseButtons.Right, 1, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + return; + } + + case Msg.WM_RBUTTONUP: { + owner.OnMouseUp (new MouseEventArgs(MouseButtons.Right, 1, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + return; + } + + case Msg.WM_RBUTTONDBLCLK: { + owner.OnDoubleClick (EventArgs.Empty); + owner.OnMouseDoubleClick (new MouseEventArgs (MouseButtons.Left, 2, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + return; + } + + case Msg.NIN_BALLOONUSERCLICK: { + owner.OnBalloonTipClicked (EventArgs.Empty); + return; + } + + case Msg.NIN_BALLOONSHOW: { + owner.OnBalloonTipShown (EventArgs.Empty); + return; + } + + case Msg.NIN_BALLOONHIDE: + case Msg.NIN_BALLOONTIMEOUT: { + owner.OnBalloonTipClosed (EventArgs.Empty); + return; + } + } + return; + } + } + base.WndProc (ref m); + } + + internal void CalculateIconRect() { + int x; + int y; + int size; + + // Icons are always square. Try to center them in the window + if (ClientRectangle.Width < ClientRectangle.Height) { + size = ClientRectangle.Width; + } else { + size = ClientRectangle.Height; + } + x = this.ClientRectangle.Width / 2 - size / 2; + y = this.ClientRectangle.Height / 2 - size / 2; + rect = new Rectangle(x, y, size, size); + + Bounds = new Rectangle (0, 0, size, size); + } + + internal override void OnPaintInternal (PaintEventArgs e) { + if (owner.icon != null) { + // At least in Gnome, the background of the panel is the same as the Menu, so we go for it + // instead of (most of the time) plain white. + e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(SystemColors.Menu), rect); + e.Graphics.DrawImage(owner.icon_bitmap, + rect, + new Rectangle (0, 0, owner.icon_bitmap.Width, owner.icon_bitmap.Height), + GraphicsUnit.Pixel); + + } + } + + internal void InternalRecreateHandle () { + base.RecreateHandle (); + } + + private void HandleSizeChanged(object sender, EventArgs e) { + owner.Recalculate (); + } + + private void HandleDoubleClick (object sender, EventArgs e) + { + owner.OnDoubleClick (e); + owner.OnMouseDoubleClick (new MouseEventArgs (MouseButtons.Left, 2, Widget.MousePosition.X, Widget.MousePosition.Y, 0)); + } + + private void HandleMouseDown (object sender, MouseEventArgs e) + { + owner.OnMouseDown (e); + } + + private void HandleMouseUp (object sender, MouseEventArgs e) + { + owner.OnMouseUp (e); + } + + private void HandleMouseMove (object sender, MouseEventArgs e) + { + owner.OnMouseMove (e); + } + } + #endregion // NotifyIconWindow Class + + #region NotifyIconBalloonWindow Class + internal class BalloonWindow : Form + { + private IntPtr owner; + private Timer timer; + + private string title; + private string text; + private ToolTipIcon icon; + + public BalloonWindow (IntPtr owner) + { + this.owner = owner; + + StartPosition = FormStartPosition.Manual; + FormBorderStyle = FormBorderStyle.None; + + MouseDown += new MouseEventHandler (HandleMouseDown); + + timer = new Timer (); + timer.Enabled = false; + timer.Tick += new EventHandler (HandleTimer); + } + + public IntPtr OwnerHandle { + get { + return owner; + } + } + + protected override void Dispose (bool disposing) + { + if (disposing) { + timer.Stop(); + timer.Dispose(); + } + base.Dispose (disposing); + } + + protected override CreateParams CreateParams { + get { + CreateParams cp; + + cp = base.CreateParams; + + cp.Style = (int)WindowStyles.WS_POPUP; + cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS; + + cp.ExStyle = (int)(WindowExStyles.WS_EX_TOOLWINDOW | WindowExStyles.WS_EX_TOPMOST); + + return cp; + } + } + + public new void Close () { + base.Close (); + XplatUI.SendMessage (owner, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONHIDE); + } + + protected override void OnShown (EventArgs e) + { + base.OnShown (e); + timer.Start (); + } + + protected override void OnPaint (PaintEventArgs e) + { + ThemeEngine.Current.DrawBalloonWindow (e.Graphics, ClientRectangle, this); + base.OnPaint (e); + } + + private void Recalculate () + { + Rectangle rect = ThemeEngine.Current.BalloonWindowRect (this); + + Left = rect.Left; + Top = rect.Top; + Width = rect.Width; + Height = rect.Height; + } + + // To be used when we have a "close button" inside balloon. + //private void HandleClick (object sender, EventArgs e) + //{ + // Close (); + //} + + private void HandleMouseDown (object sender, MouseEventArgs e) + { + XplatUI.SendMessage (owner, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONUSERCLICK); + base.Close (); + } + + private void HandleTimer (object sender, EventArgs e) + { + timer.Stop (); + XplatUI.SendMessage (owner, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONTIMEOUT); + base.Close (); + } + + internal StringFormat Format { + get { + StringFormat format = new StringFormat (); + format.Alignment = StringAlignment.Near; + format.HotkeyPrefix = HotkeyPrefix.Hide; + + return format; + } + } + + public new ToolTipIcon Icon { + get { return this.icon; } + set { + if (value == this.icon) + return; + + this.icon = value; + Recalculate (); + } + } + + public string Title { + get { return this.title; } + set { + if (value == this.title) + return; + + this.title = value; + Recalculate (); + } + } + + public override string Text { + get { return this.text; } + set { + if (value == this.text) + return; + + this.text = value; + Recalculate (); + } + } + + public int Timeout { + get { return timer.Interval; } + set { + // Some systems theres a limitiation in timeout, WinXP is between 10k and 30k. + if (value < 10000) + timer.Interval = 10000; + else if (value > 30000) + timer.Interval = 30000; + else + timer.Interval = value; + } + } + } + #endregion // NotifyIconBalloonWindow Class + + #region Public Constructors + public NotifyIcon() { + window = new NotifyIconWindow(this); + systray_active = false; + + balloon_title = ""; + balloon_text = ""; + } + + public NotifyIcon(System.ComponentModel.IContainer container) : this() { + } + #endregion // Public Constructors + + #region Public Methods + public void ShowBalloonTip (int timeout) + { + ShowBalloonTip(timeout, balloon_title, balloon_text, balloon_icon); + } + + public void ShowBalloonTip(int timeout, string tipTitle, string tipText, ToolTipIcon tipIcon) + { + XplatUI.SystrayBalloon(window.Handle, timeout, tipTitle, tipText, tipIcon); + } + #endregion Public Methods + + #region Private Methods + private void OnBalloonTipClicked (EventArgs e) + { + EventHandler eh = (EventHandler)(Events [BalloonTipClickedEvent]); + if (eh != null) + eh (this, e); + } + + private void OnBalloonTipClosed (EventArgs e) + { + EventHandler eh = (EventHandler)(Events [BalloonTipClosedEvent]); + if (eh != null) + eh (this, e); + } + + private void OnBalloonTipShown (EventArgs e) + { + EventHandler eh = (EventHandler)(Events [BalloonTipShownEvent]); + if (eh != null) + eh (this, e); + } + + private void OnClick (EventArgs e) + { + EventHandler eh = (EventHandler)(Events [ClickEvent]); + if (eh != null) + eh (this, e); + } + + private void OnDoubleClick (EventArgs e) + { + double_click = true; + EventHandler eh = (EventHandler)(Events [DoubleClickEvent]); + if (eh != null) + eh (this, e); + } + + private void OnMouseClick (MouseEventArgs e) + { + MouseEventHandler eh = (MouseEventHandler)(Events[MouseClickEvent]); + if (eh != null) + eh (this, e); + } + + private void OnMouseDoubleClick (MouseEventArgs e) + { + MouseEventHandler eh = (MouseEventHandler)(Events[MouseDoubleClickEvent]); + if (eh != null) + eh (this, e); + } + + private void OnMouseDown (MouseEventArgs e) + { + MouseEventHandler eh = (MouseEventHandler)(Events [MouseDownEvent]); + if (eh != null) + eh (this, e); + } + + private void OnMouseUp (MouseEventArgs e) + { + if ((e.Button & MouseButtons.Right) == MouseButtons.Right) { + if (context_menu_strip != null) { + XplatUI.SetForegroundWindow (window.Handle); + context_menu_strip.Show (window, new Point (e.X, e.Y), ToolStripDropDownDirection.AboveLeft); + } + } + + MouseEventHandler eh = (MouseEventHandler)(Events [MouseUpEvent]); + if (eh != null) + eh (this, e); + + if (!double_click) { + OnClick (EventArgs.Empty); + OnMouseClick (e); + double_click = false; + } + } + + private void OnMouseMove (MouseEventArgs e) + { + MouseEventHandler eh = (MouseEventHandler)(Events [MouseMoveEvent]); + if (eh != null) + eh (this, e); + } + + private void Recalculate () + { + window.CalculateIconRect (); + + if (!Visible || (text == string.Empty && icon == null)) { + HideSystray (); + } else { + + if (systray_active) + UpdateSystray (); + else + ShowSystray (); + } + } + + private void ShowSystray() + { + if (icon == null) + return; + + icon_bitmap = icon.ToBitmap(); + + systray_active = true; + XplatUI.SystrayAdd(window.Handle, text, icon, out tooltip); + } + + private void HideSystray() + { + if (!systray_active) { + return; + } + + systray_active = false; + XplatUI.SystrayRemove(window.Handle, ref tooltip); + } + + private void UpdateSystray() + { + if (icon_bitmap != null) { + icon_bitmap.Dispose(); + } + + if (icon != null) { + icon_bitmap = icon.ToBitmap(); + } + + window.Invalidate(); + XplatUI.SystrayChange(window.Handle, text, icon, ref tooltip); + } + #endregion // Private Methods + + #region Public Instance Properties + [DefaultValue ("None")] + public ToolTipIcon BalloonTipIcon { + get { return this.balloon_icon; } + set { + if (value == this.balloon_icon) + return; + + this.balloon_icon = value; + } + } + + [Localizable(true)] + [DefaultValue ("")] + //[Editor ("System.ComponentModel.Design.MultilineStringEditor, " + Consts.AssemblySystem_Design, + //"System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] + public string BalloonTipText { + get { return this.balloon_text; } + set { + if (value == this.balloon_text) + return; + + this.balloon_text = value; + } + } + + [Localizable(true)] + [DefaultValue ("")] + public string BalloonTipTitle { + get { return this.balloon_title; } + set { + if (value == this.balloon_title) + return; + + this.balloon_title = value; + } + } + + + + [DefaultValue (null)] + public ContextMenuStrip ContextMenuStrip { + get { return this.context_menu_strip; } + set { + if (this.context_menu_strip != value) { + this.context_menu_strip = value; + window.ContextMenuStrip = value; + } + } + } + + [Localizable(true)] + [DefaultValue(null)] + public Icon Icon { + get { + return icon; + } + + set { + if (icon != value) { + icon = value; + Recalculate (); + } + } + } + + [Localizable (false)] + [Bindable (true)] + [TypeConverter (typeof (StringConverter))] + [DefaultValue (null)] + public object Tag { + get { return this.tag; } + set { this.tag = value; } + } + + [DefaultValue ("")] + //[Editor ("System.ComponentModel.Design.MultilineStringEditor, " + Consts.AssemblySystem_Design, + // typeof (System.Drawing.Design.UITypeEditor))] + [Localizable (true)] + public string Text { + get { + return text; + } + + set { + if (text != value) { + if (value.Length >= 64) { + throw new ArgumentException("ToolTip length must be less than 64 characters long", "Text"); + } + text = value; + Recalculate (); + } + } + } + + [Localizable(true)] + [DefaultValue(false)] + public bool Visible { + get { + return visible; + } + + set { + if (visible != value) { + visible = value; + + // Let our control know, too + window.is_visible = value; + + if (visible) { + ShowSystray (); + } else { + HideSystray(); + } + } + } + } + #endregion // Public Instance Properties + + #region Protected Instance Methods + protected override void Dispose(bool disposing) { + if (visible) + HideSystray(); + + if (icon_bitmap != null) { + icon_bitmap.Dispose(); + } + + if (disposing) + icon = null; + + base.Dispose (disposing); + } + + #endregion // Protected Instance Methods + + #region Events + static object ClickEvent = new object (); + static object DoubleClickEvent = new object (); + static object MouseDownEvent = new object (); + static object MouseMoveEvent = new object (); + static object MouseUpEvent = new object (); + static object BalloonTipClickedEvent = new object (); + static object BalloonTipClosedEvent = new object (); + static object BalloonTipShownEvent = new object (); + static object MouseClickEvent = new object (); + static object MouseDoubleClickEvent = new object (); + + [MWFCategory("Action")] + public event EventHandler BalloonTipClicked { + add { Events.AddHandler (BalloonTipClickedEvent, value); } + remove { Events.RemoveHandler (BalloonTipClickedEvent, value); } + } + + [MWFCategory("Action")] + public event EventHandler BalloonTipClosed { + add { Events.AddHandler (BalloonTipClosedEvent, value); } + remove { Events.RemoveHandler (BalloonTipClosedEvent, value); } + } + + [MWFCategory("Action")] + public event EventHandler BalloonTipShown { + add { Events.AddHandler (BalloonTipShownEvent, value); } + remove { Events.RemoveHandler (BalloonTipShownEvent, value); } + } + + [MWFCategory("Action")] + public event MouseEventHandler MouseClick { + add { Events.AddHandler (MouseClickEvent, value); } + remove { Events.RemoveHandler (MouseClickEvent, value); } + } + + [MWFCategory ("Action")] + public event MouseEventHandler MouseDoubleClick { + add { Events.AddHandler (MouseDoubleClickEvent, value); } + remove { Events.RemoveHandler (MouseDoubleClickEvent, value); } + } + + [MWFCategory("Action")] + public event EventHandler Click { + add { Events.AddHandler (ClickEvent, value); } + remove { Events.RemoveHandler (ClickEvent, value); } + } + + [MWFCategory("Action")] + public event EventHandler DoubleClick { + add { Events.AddHandler (DoubleClickEvent, value); } + remove { Events.RemoveHandler (DoubleClickEvent, value); } + } + + public event MouseEventHandler MouseDown { + add { Events.AddHandler (MouseDownEvent, value); } + remove { Events.RemoveHandler (MouseDownEvent, value); } + } + + public event MouseEventHandler MouseMove { + add { Events.AddHandler (MouseMoveEvent, value); } + remove { Events.RemoveHandler (MouseMoveEvent, value); } + } + + public event MouseEventHandler MouseUp { + add { Events.AddHandler (MouseUpEvent, value); } + remove { Events.RemoveHandler (MouseUpEvent, value); } + } + + #endregion // Events + } +} |
