Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolTip.cs')
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolTip.cs453
1 files changed, 453 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolTip.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolTip.cs
new file mode 100644
index 00000000000..19efe7fe1bc
--- /dev/null
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ToolTip.cs
@@ -0,0 +1,453 @@
+// 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) 2004 Novell, Inc. (http://www.novell.com)
+//
+// Authors:
+// Peter Bartok pbartok@novell.com
+//
+//
+
+
+// COMPLETE
+
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+
+namespace System.Windows.Forms {
+ [ProvideProperty ("ToolTip", typeof(System.Windows.Forms.Control))]
+ [ToolboxItemFilter("System.Windows.Forms", ToolboxItemFilterType.Allow)]
+ public sealed class ToolTip : System.ComponentModel.Component, System.ComponentModel.IExtenderProvider {
+ #region Local variables
+ internal bool is_active;
+ internal int automatic_delay;
+ internal int autopop_delay;
+ internal int initial_delay;
+ internal int re_show_delay;
+ internal bool show_always;
+
+ internal ToolTipWindow tooltip_window; // The actual tooltip window
+ internal Hashtable tooltip_strings; // List of strings for each control, indexed by control
+ internal ArrayList controls;
+ internal Control active_control; // Control for which the tooltip is currently displayed
+ internal Control last_control; // last control the mouse was in
+ internal Size display_size; // Size of the screen
+ internal Timer timer; // Used for the various intervals
+ #endregion // Local variables
+
+ #region ToolTipWindow Class
+ internal class ToolTipWindow : Control {
+ #region ToolTipWindow Class Local Variables
+ internal StringFormat string_format;
+ internal ToolTip owner;
+ #endregion // ToolTipWindow Class Local Variables
+
+ #region ToolTipWindow Class Constructor
+ internal ToolTipWindow(ToolTip owner) : base() {
+ this.owner = owner;
+
+ string_format = new StringFormat();
+ string_format.LineAlignment = StringAlignment.Center;
+ string_format.Alignment = StringAlignment.Center;
+ string_format.FormatFlags = StringFormatFlags.NoWrap;
+
+ Visible = false;
+ Size = new Size(100, 20);
+ ForeColor = ThemeEngine.Current.ColorInfoText;
+ BackColor = ThemeEngine.Current.ColorInfo;
+
+ VisibleChanged += new EventHandler(ToolTipWindow_VisibleChanged);
+
+ SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
+ SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
+ }
+
+ #endregion // ToolTipWindow Class Constructor
+
+ #region ToolTipWindow Class Protected Instance Methods
+ protected override void OnCreateControl() {
+ base.OnCreateControl ();
+ XplatUI.SetTopmost(this.window.Handle, IntPtr.Zero, true);
+ }
+
+ 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)(WindowStyles.WS_EX_TOOLWINDOW | WindowStyles.WS_EX_TOPMOST);
+
+ return cp;
+ }
+ }
+
+ protected override void OnPaint(PaintEventArgs pevent) {
+ // We don't do double-buffering on purpose:
+ // 1) we'd have to meddle with is_visible, it destroys the buffers if !visible
+ // 2) We don't draw much, no need to double buffer
+ ThemeEngine.Current.DrawToolTip(pevent.Graphics, ClientRectangle, this);
+
+ base.OnPaint(pevent);
+ }
+
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ this.string_format.Dispose();
+ }
+ base.Dispose (disposing);
+ }
+
+ protected override void WndProc(ref Message m) {
+ if (m.Msg == (int)Msg.WM_SETFOCUS) {
+ if (m.WParam != IntPtr.Zero) {
+ XplatUI.SetFocus(m.WParam);
+ }
+ }
+ base.WndProc (ref m);
+ }
+
+
+ #endregion // ToolTipWindow Class Protected Instance Methods
+
+ #region ToolTipWindow Class Private Methods
+ private void ToolTipWindow_VisibleChanged(object sender, EventArgs e) {
+ Control control = (Control)sender;
+
+ if (control.is_visible) {
+ XplatUI.SetTopmost(control.window.Handle, IntPtr.Zero, true);
+ } else {
+ XplatUI.SetTopmost(control.window.Handle, IntPtr.Zero, false);
+ }
+ }
+ #endregion // ToolTipWindow Class Protected Instance Methods
+ }
+ #endregion // ToolTipWindow Class
+
+ #region Public Constructors & Destructors
+ public ToolTip() {
+ XplatUI.GetDisplaySize(out display_size);
+
+ // Defaults from MS
+ is_active = true;
+ automatic_delay = 500;
+ autopop_delay = 5000;
+ initial_delay = 500;
+ re_show_delay = 100;
+ show_always = false;
+
+ tooltip_strings = new Hashtable(5);
+ controls = new ArrayList(5);
+
+ tooltip_window = new ToolTipWindow(this);
+ tooltip_window.MouseLeave += new EventHandler(control_MouseLeave);
+
+ timer = new Timer();
+ timer.Enabled = false;
+ timer.Tick +=new EventHandler(timer_Tick);
+ }
+
+ public ToolTip(System.ComponentModel.IContainer cont) : this() {
+ // Dunno why I'd need the container
+ }
+
+ ~ToolTip() {
+ }
+ #endregion // Public Constructors & Destructors
+
+ #region Public Instance Properties
+ [DefaultValue (true)]
+ public bool Active {
+ get {
+ return is_active;
+ }
+
+ set {
+ if (is_active != value) {
+ is_active = value;
+
+ if (tooltip_window.Visible) {
+ tooltip_window.Visible = false;
+ active_control = null;
+ }
+ }
+ }
+ }
+
+ [DefaultValue (500)]
+ [RefreshProperties (RefreshProperties.All)]
+ public int AutomaticDelay {
+ get {
+ return automatic_delay;
+ }
+
+ set {
+ if (automatic_delay != value) {
+ automatic_delay = value;
+ autopop_delay = automatic_delay * 10;
+ initial_delay = automatic_delay;
+ re_show_delay = automatic_delay / 5;
+ }
+ }
+ }
+
+ [RefreshProperties (RefreshProperties.All)]
+ public int AutoPopDelay {
+ get {
+ return autopop_delay;
+ }
+
+ set {
+ if (autopop_delay != value) {
+ autopop_delay = value;
+ }
+ }
+ }
+
+ [RefreshProperties (RefreshProperties.All)]
+ public int InitialDelay {
+ get {
+ return initial_delay;
+ }
+
+ set {
+ if (initial_delay != value) {
+ initial_delay = value;
+ }
+ }
+ }
+
+ [RefreshProperties (RefreshProperties.All)]
+ public int ReshowDelay {
+ get {
+ return re_show_delay;
+ }
+
+ set {
+ if (re_show_delay != value) {
+ re_show_delay = value;
+ }
+ }
+ }
+
+ [DefaultValue (false)]
+ public bool ShowAlways {
+ get {
+ return show_always;
+ }
+
+ set {
+ if (show_always != value) {
+ show_always = value;
+ }
+ }
+ }
+ #endregion // Public Instance Properties
+
+ #region Public Instance Methods
+ public bool CanExtend(object target) {
+ return false;
+ }
+
+ [Localizable (true)]
+ [DefaultValue ("")]
+ public string GetToolTip(Control control) {
+ string tooltip = (string)tooltip_strings[control];
+ if (tooltip == null)
+ return "";
+ return tooltip;
+ }
+
+ public void RemoveAll() {
+ tooltip_strings.Clear();
+ controls.Clear();
+ }
+
+ public void SetToolTip(Control control, string caption) {
+ tooltip_strings[control] = caption;
+
+ // no need for duplicates
+ if (!controls.Contains(control)) {
+ control.MouseEnter += new EventHandler(control_MouseEnter);
+ control.MouseMove += new MouseEventHandler(control_MouseMove);
+ control.MouseLeave += new EventHandler(control_MouseLeave);
+ controls.Add(control);
+ }
+
+ // if SetToolTip is called from a control and the mouse is currently over that control,
+ // make sure that tooltip_window.Text gets updated
+ if (caption != null && last_control == control) {
+ Size size = ThemeEngine.Current.ToolTipSize(tooltip_window, caption);
+ tooltip_window.Width = size.Width;
+ tooltip_window.Height = size.Height;
+ tooltip_window.Text = caption;
+ }
+ }
+
+ public override string ToString() {
+ return base.ToString() + " InitialDelay: " + initial_delay + ", ShowAlways: " + show_always;
+ }
+ #endregion // Public Instance Methods
+
+ #region Protected Instance Methods
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ // Mop up the mess; or should we wait for the GC to kick in?
+ timer.Stop();
+ timer.Dispose();
+
+ // Not sure if we should clean up tooltip_window
+ tooltip_window.Dispose();
+
+ tooltip_strings.Clear();
+
+ controls.Clear();
+ }
+ }
+ #endregion // Protected Instance Methods
+
+ #region Private Methods
+ private void control_MouseEnter(object sender, EventArgs e) {
+ string text;
+
+ last_control = (Control)sender;
+
+ // Whatever we're displaying right now, we don't want it anymore
+ tooltip_window.Visible = false;
+ timer.Stop();
+
+ // if we're in the same control as before (how'd that happen?) or if we're not active, leave
+ if (!is_active || (active_control == (Control)sender)) {
+ return;
+ }
+
+ if (!show_always) {
+ if (((Control)sender).GetContainerControl().ActiveControl == null) {
+ return;
+ }
+ }
+
+ text = (string)tooltip_strings[sender];
+ if (text != null) {
+ Size size;
+
+ size = ThemeEngine.Current.ToolTipSize(tooltip_window, text);
+ tooltip_window.Width = size.Width;
+ tooltip_window.Height = size.Height;
+ tooltip_window.Text = text;
+
+ // FIXME - this needs to be improved; the tooltip will show up under the mouse, which is annoying; use cursor size once implemented
+
+ if ((Control.MousePosition.X+1+tooltip_window.Width) < display_size.Width) {
+ tooltip_window.Left = Control.MousePosition.X+1;
+ } else {
+ tooltip_window.Left = display_size.Width-tooltip_window.Width;
+ }
+
+ if ((Control.MousePosition.Y+tooltip_window.Height)<display_size.Height) {
+ tooltip_window.Top = Control.MousePosition.Y;
+ } else {
+ tooltip_window.Top = Control.MousePosition.Y-tooltip_window.Height;
+ }
+
+ // Since we get the mouse enter before the mouse leave, active_control will still be non-null if we were in a
+ // tooltip'd control; should prolly check on X11 too, and make sure that driver behaves the same way
+ if (active_control == null) {
+ timer.Interval = initial_delay;
+ } else {
+ timer.Interval = re_show_delay;
+ }
+
+ active_control = (Control)sender;
+
+ // We're all set, lets wake the timer (which will then make us visible)
+ timer.Enabled = true;
+ }
+ }
+
+ private void timer_Tick(object sender, EventArgs e) {
+ // Show our pretty selves
+ timer.Stop();
+
+ // FIXME - Should not need this check../
+ if (tooltip_window.IsDisposed) {
+ return;
+ }
+
+ if (!tooltip_window.Visible) {
+ // The initial_delay timer kicked in
+ tooltip_window.Visible = true;
+ timer.Interval = autopop_delay;
+ timer.Start();
+ } else {
+ // The autopop_delay timer happened
+ tooltip_window.Visible = false;
+ }
+ }
+
+
+ private bool MouseInControl(Control control) {
+ Point m;
+ Point c;
+ Size cw;
+
+ if (control == null) {
+ return false;
+ }
+
+ m = Control.MousePosition;
+ c = new Point(control.Bounds.X, control.Bounds.Y);
+ if (control.parent != null) {
+ c = control.parent.PointToScreen(c);
+ }
+ cw = control.ClientSize;
+
+ if (c.X<=m.X && m.X<(c.X+cw.Width) &&
+ c.Y<=m.Y && m.Y<(c.Y+cw.Height)) {
+ return true;
+ }
+ return false;
+ }
+
+ private void control_MouseLeave(object sender, EventArgs e) {
+ // In case the timer is still running, stop it
+ timer.Stop();
+
+ if (!MouseInControl(tooltip_window) && !MouseInControl(active_control)) {
+ active_control = null;
+ tooltip_window.Visible = false;
+ }
+
+ if (last_control == (Control)sender)
+ last_control = null;
+ }
+
+ private void control_MouseMove(object sender, MouseEventArgs e) {
+ // Restart the interval, the mouse moved
+ timer.Stop();
+ timer.Start();
+
+ }
+ #endregion // Private Methods
+ }
+}