(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolTip.cs
blob83891e6d6e64fe90c457435dd447139f6f3e87fd
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004 Novell, Inc. (http://www.novell.com)
22 // Authors:
23 // Peter Bartok pbartok@novell.com
26 // $Revision: 1.4 $
27 // $Log: ToolTip.cs,v $
28 // Revision 1.4 2004/11/08 20:49:35 pbartok
29 // - Fixed arguments for updated SetTopmost function
30 // - Fixed usage of PointToClient
32 // Revision 1.3 2004/10/19 06:04:59 ravindra
33 // Fixed constructor.
35 // Revision 1.2 2004/10/18 06:28:30 ravindra
36 // Suppressed a warning message.
38 // Revision 1.1 2004/10/18 05:19:57 pbartok
39 // - Complete implementation
44 // COMPLETE
46 using System.Collections;
47 using System.ComponentModel;
48 using System.Drawing;
50 namespace System.Windows.Forms {
51 public sealed class ToolTip : System.ComponentModel.Component, System.ComponentModel.IExtenderProvider {
52 #region Local variables
53 internal bool is_active;
54 internal int automatic_delay;
55 internal int autopop_delay;
56 internal int initial_delay;
57 internal int re_show_delay;
58 internal bool show_always;
60 internal ToolTipWindow tooltip_window; // The actual tooltip window
61 internal Hashtable tooltip_strings; // List of strings for each control, indexed by control
62 internal Control active_control; // Control for which the tooltip is currently displayed
63 internal Control last_control; // last control the mouse was in; null if the last control did not have a tooltip
64 internal Size display_size; // Size of the screen
65 internal Timer timer; // Used for the various intervals
66 #endregion // Local variables
68 #region ToolTipWindow Class
69 internal class ToolTipWindow : Control {
70 #region ToolTipWindow Class Local Variables
71 internal StringFormat string_format;
72 internal ToolTip owner;
73 #endregion // ToolTipWindow Class Local Variables
75 #region ToolTipWindow Class Constructor
76 internal ToolTipWindow(ToolTip owner) : base() {
77 this.owner = owner;
79 string_format = new StringFormat();
80 string_format.LineAlignment = StringAlignment.Center;
81 string_format.Alignment = StringAlignment.Center;
82 string_format.FormatFlags = StringFormatFlags.NoWrap;
84 Visible = false;
85 Size = new Size(100, 20);
86 ForeColor = ThemeEngine.Current.ColorInfoText;
87 BackColor = ThemeEngine.Current.ColorInfoWindow;
89 VisibleChanged += new EventHandler(ToolTipWindow_VisibleChanged);
91 SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
92 SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
95 #endregion // ToolTipWindow Class Constructor
97 #region ToolTipWindow Class Protected Instance Methods
98 protected override void OnCreateControl() {
99 base.OnCreateControl ();
100 XplatUI.SetTopmost(this.window.Handle, IntPtr.Zero, true);
103 protected override CreateParams CreateParams {
104 get {
105 CreateParams cp;
107 cp = base.CreateParams;
109 cp.Style = (int)WindowStyles.WS_POPUP;
110 cp.Style |= (int)WindowStyles.WS_CLIPSIBLINGS;
112 cp.ExStyle |= (int)WindowStyles.WS_EX_TOOLWINDOW;
114 return cp;
118 protected override void OnPaint(PaintEventArgs pevent) {
119 // We don't do double-buffering on purpose:
120 // 1) we'd have to meddle with is_visible, it destroys the buffers if !visible
121 // 2) We don't draw much, no need to double buffer
122 ThemeEngine.Current.DrawToolTip(pevent.Graphics, ClientRectangle, owner);
125 protected override void Dispose(bool disposing) {
126 if (disposing) {
127 this.string_format.Dispose();
129 base.Dispose (disposing);
132 #endregion // ToolTipWindow Class Protected Instance Methods
134 #region ToolTipWindow Class Private Methods
135 private void ToolTipWindow_VisibleChanged(object sender, EventArgs e) {
136 Control control = (Control)sender;
138 if (control.is_visible) {
139 XplatUI.SetTopmost(control.window.Handle, IntPtr.Zero, true);
140 } else {
141 XplatUI.SetTopmost(control.window.Handle, IntPtr.Zero, false);
144 #endregion // ToolTipWindow Class Protected Instance Methods
146 #endregion // ToolTipWindow Class
148 #region Public Constructors & Destructors
149 public ToolTip() {
150 XplatUI.GetDisplaySize(out display_size);
152 // Defaults from MS
153 is_active = true;
154 automatic_delay = 500;
155 autopop_delay = 5000;
156 initial_delay = 500;
157 re_show_delay = 100;
158 show_always = false;
160 tooltip_strings = new Hashtable(5);
162 tooltip_window = new ToolTipWindow(this);
163 tooltip_window.MouseLeave += new EventHandler(control_MouseLeave);
165 timer = new Timer();
166 timer.Enabled = false;
167 timer.Tick +=new EventHandler(timer_Tick);
170 public ToolTip(System.ComponentModel.IContainer cont) : this() {
171 // Dunno why I'd need the container
174 ~ToolTip() {
176 #endregion // Public Constructors & Destructors
178 #region Public Instance Properties
179 public bool Active {
180 get {
181 return is_active;
184 set {
185 if (is_active != value) {
186 is_active = value;
188 if (tooltip_window.Visible) {
189 tooltip_window.Visible = false;
190 active_control = null;
196 public int AutomaticDelay {
197 get {
198 return automatic_delay;
201 set {
202 if (automatic_delay != value) {
203 automatic_delay = value;
204 autopop_delay = automatic_delay * 10;
205 initial_delay = automatic_delay;
206 re_show_delay = automatic_delay / 5;
211 public int AutoPopDelay {
212 get {
213 return autopop_delay;
216 set {
217 if (autopop_delay != value) {
218 autopop_delay = value;
223 public int InitialDelay {
224 get {
225 return initial_delay;
228 set {
229 if (initial_delay != value) {
230 initial_delay = value;
235 public int ReshowDelay {
236 get {
237 return re_show_delay;
240 set {
241 if (re_show_delay != value) {
242 re_show_delay = value;
247 public bool ShowAlways {
248 get {
249 return show_always;
252 set {
253 if (show_always != value) {
254 show_always = value;
258 #endregion // Public Instance Properties
260 #region Public Instance Methods
261 public bool CanExtend(object target) {
262 return false;
265 public string GetToolTip(Control control) {
266 return (string)tooltip_strings[control];
269 public void RemoveAll() {
270 tooltip_strings.Clear();
273 public void SetToolTip(Control control, string caption) {
274 tooltip_strings[control] = caption;
276 control.MouseEnter += new EventHandler(control_MouseEnter);
277 control.MouseMove += new MouseEventHandler(control_MouseMove);
278 control.MouseLeave += new EventHandler(control_MouseLeave);
281 public override string ToString() {
282 return base.ToString() + " InitialDelay: " + initial_delay + ", ShowAlways: " + show_always;
284 #endregion // Public Instance Methods
286 #region Protected Instance Methods
287 protected override void Dispose(bool disposing) {
288 if (disposing) {
289 // Mop up the mess; or should we wait for the GC to kick in?
290 timer.Stop();
291 timer.Dispose();
293 // Not sure if we should clean up tooltip_window
294 tooltip_window.Dispose();
296 tooltip_strings.Clear();
299 #endregion // Protected Instance Methods
301 #region Private Methods
302 private void control_MouseEnter(object sender, EventArgs e) {
303 string text;
305 // Whatever we're displaying right now, we don't want it anymore
306 tooltip_window.Visible = false;
307 timer.Stop();
309 // if we're in the same control as before (how'd that happen?) or if we're not active, leave
310 if (!is_active || (active_control == (Control)sender)) {
311 return;
314 // As of this writing, our MWF implementation had no clue what an active control was :-(
315 if (!show_always) {
316 if (((Control)sender).GetContainerControl().ActiveControl == null) {
317 return;
321 text = (string)tooltip_strings[sender];
322 if (text != null) {
323 Size size;
325 size = ThemeEngine.Current.ToolTipSize(this, text);
326 tooltip_window.Width = size.Width;
327 tooltip_window.Height = size.Height;
328 tooltip_window.Text = text;
330 // FIXME - this needs to be improved; the tooltip will show up under the mouse, which is annoying; use cursor size once implemented
332 if ((Control.MousePosition.X+1+tooltip_window.Width) < display_size.Width) {
333 tooltip_window.Left = Control.MousePosition.X+1;
334 } else {
335 tooltip_window.Left = display_size.Width-tooltip_window.Width;
338 if ((Control.MousePosition.Y+tooltip_window.Height)<display_size.Height) {
339 tooltip_window.Top = Control.MousePosition.Y;
340 } else {
341 tooltip_window.Top = Control.MousePosition.Y-tooltip_window.Height;
344 // Since we get the mouse enter before the mouse leave, active_control will still be non-null if we were in a
345 // tooltip'd control; should prolly check on X11 too, and make sure that driver behaves the same way
346 if (active_control == null) {
347 timer.Interval = initial_delay;
348 } else {
349 timer.Interval = re_show_delay;
352 active_control = (Control)sender;
354 // We're all set, lets wake the timer (which will then make us visible)
355 timer.Enabled = true;
359 private void timer_Tick(object sender, EventArgs e) {
360 // Show our pretty selves
361 timer.Stop();
362 if (!tooltip_window.Visible) {
363 // The initial_delay timer kicked in
364 tooltip_window.Visible = true;
365 timer.Interval = autopop_delay;
366 timer.Start();
367 } else {
368 // The autopop_delay timer happened
369 tooltip_window.Visible = false;
374 private bool MouseInControl(Control control) {
375 Point m;
376 Point c;
377 Size cw;
379 if (control == null) {
380 return false;
383 m = Control.MousePosition;
384 c = new Point(control.Bounds.X, control.Bounds.Y);
385 if (control.parent != null) {
386 c = control.parent.PointToScreen(c);
388 cw = control.ClientSize;
390 if (c.X<=m.X && m.X<(c.X+cw.Width) &&
391 c.Y<=m.Y && m.Y<(c.Y+cw.Height)) {
392 return true;
394 return false;
397 private void control_MouseLeave(object sender, EventArgs e) {
398 // In case the timer is still running, stop it
399 timer.Stop();
401 if (!MouseInControl(tooltip_window) && !MouseInControl(active_control)) {
402 active_control = null;
403 tooltip_window.Visible = false;
407 private void control_MouseMove(object sender, MouseEventArgs e) {
408 // Restart the interval, the mouse moved
409 timer.Stop();
410 timer.Start();
413 #endregion // Private Methods