UpDownBase.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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.
  19. //
  20. // Copyright (c) 2004 Novell, Inc.
  21. //
  22. // Authors:
  23. // Miguel de Icaza ([email protected]).
  24. //
  25. //
  26. /*
  27. TODO:
  28. - Force the size of the entry: it can not be resized vertically
  29. ever, the size is set by the size of the font
  30. */
  31. using System;
  32. using System.Drawing;
  33. namespace System.Windows.Forms {
  34. public abstract class UpDownBase : ContainerControl {
  35. internal class Spinner : Control, IDisposable {
  36. UpDownBase updownbase;
  37. Rectangle up, down, pressed;
  38. Timer timer;
  39. bool up_pressed, down_pressed;
  40. bool captured, mouse_in;
  41. //
  42. // Interval values
  43. //
  44. const int StartInterval = 1000;
  45. const int RepeatInterval = 400;
  46. const int ChangeInterval = 75;
  47. const int MinimumInterval = 20;
  48. internal Spinner (UpDownBase updownbase)
  49. {
  50. this.updownbase = updownbase;
  51. }
  52. protected override void OnPaint (PaintEventArgs args)
  53. {
  54. Draw (args.ClipRectangle);
  55. args.Graphics.DrawImage (ImageBuffer, 0, 0);
  56. }
  57. protected override void OnLayout (LayoutEventArgs args)
  58. {
  59. base.OnLayout (args);
  60. Rectangle bounds = Bounds;
  61. up = new Rectangle (0, 0, bounds.Width, bounds.Height/2);
  62. down = new Rectangle (0, bounds.Height/2, bounds.Width, bounds.Height/2);
  63. }
  64. protected override void OnMouseDown (MouseEventArgs args)
  65. {
  66. base.OnMouseDown (args);
  67. if (args.Button != MouseButtons.Left)
  68. return;
  69. if (up.Contains (args.X, args.Y)){
  70. up_pressed = true;
  71. pressed = up;
  72. } else if (down.Contains (args.X, args.Y)){
  73. down_pressed = true;
  74. pressed = down;
  75. } else
  76. return;
  77. Click ();
  78. Invalidate (pressed);
  79. Capture = true;
  80. InitTimer ();
  81. mouse_in = down_pressed | up_pressed;
  82. }
  83. protected override void OnMouseUp (MouseEventArgs args)
  84. {
  85. if (Capture){
  86. if (up_pressed){
  87. up_pressed = false;
  88. Invalidate (up);
  89. }
  90. if (down_pressed){
  91. down_pressed = false;
  92. Invalidate (down);
  93. }
  94. }
  95. Capture = false;
  96. }
  97. //
  98. // Sets up the auto-repeat timer, we give a one second
  99. // delay, and then we use the keyboard settings for auto-repeat.
  100. //
  101. void InitTimer ()
  102. {
  103. timer = new Timer ();
  104. int kd = SystemInformation.KeyboardDelay;
  105. kd = kd < 0 ? 0 : (kd > 4 ? 4 : kd);
  106. timer.Interval = StartInterval;
  107. timer.Tick += new EventHandler (ClockTick);
  108. timer.Enabled = true;
  109. }
  110. void ClockTick (object o, EventArgs a)
  111. {
  112. if (timer == null)
  113. throw new Exception ("The timer that owns this callback is null!");
  114. int interval = timer.Interval;
  115. if (interval == StartInterval)
  116. interval = RepeatInterval;
  117. else
  118. interval -= ChangeInterval;
  119. if (interval < MinimumInterval)
  120. interval = MinimumInterval;
  121. timer.Interval = interval;
  122. Click ();
  123. }
  124. void Click ()
  125. {
  126. if (up_pressed)
  127. updownbase.UpButton ();
  128. if (down_pressed)
  129. updownbase.DownButton ();
  130. }
  131. protected override void OnMouseMove (MouseEventArgs args)
  132. {
  133. base.OnMouseMove (args);
  134. if (Capture){
  135. bool old = mouse_in;
  136. if (pressed.Contains (args.X, args.Y)){
  137. if (timer == null)
  138. InitTimer ();
  139. mouse_in = true;
  140. } else {
  141. if (timer != null){
  142. timer.Enabled = false;
  143. timer.Dispose ();
  144. timer = null;
  145. }
  146. mouse_in = false;
  147. }
  148. if (mouse_in ^ old){
  149. Console.WriteLine ("STATE CHANGE");
  150. if (mouse_in)
  151. Click ();
  152. Invalidate (pressed);
  153. }
  154. }
  155. }
  156. void DrawUp ()
  157. {
  158. ButtonState bs;
  159. bs = mouse_in && up_pressed ? ButtonState.Pushed : ButtonState.Normal;
  160. ThemeEngine.Current.CPDrawScrollButton (DeviceContext, up, ScrollButton.Up, bs);
  161. }
  162. void DrawDown ()
  163. {
  164. ButtonState bs;
  165. bs = mouse_in && down_pressed ? ButtonState.Pushed : ButtonState.Normal;
  166. ThemeEngine.Current.CPDrawScrollButton (DeviceContext, down, ScrollButton.Down, bs);
  167. }
  168. void Draw (Rectangle clip)
  169. {
  170. if (clip.Contains (up))
  171. DrawUp ();
  172. if (clip.Contains (down))
  173. DrawDown ();
  174. }
  175. void IDisposable.Dispose ()
  176. {
  177. if (timer != null){
  178. timer.Stop ();
  179. timer.Dispose ();
  180. }
  181. timer = null;
  182. base.Dispose ();
  183. }
  184. }
  185. int desired_height = 0;
  186. Label entry;
  187. Spinner spinner;
  188. int scrollbar_button_size = ThemeEngine.Current.ScrollBarButtonSize;
  189. public UpDownBase () : base ()
  190. {
  191. SuspendLayout ();
  192. entry = new Label ();
  193. entry.Text = "I will be an Entry";
  194. entry.Font = Font;
  195. entry.Size = new Size (100, Font.Height + 4);
  196. entry.Location = new Point (0, 0);
  197. Controls.Add (entry);
  198. spinner = new Spinner (this);
  199. Controls.Add (spinner);
  200. ResumeLayout ();
  201. }
  202. #region UpDownBase overwritten methods
  203. protected override void OnMouseWheel (MouseEventArgs args)
  204. {
  205. base.OnMouseWheel (args);
  206. if (args.Delta > 0)
  207. UpButton ();
  208. else if (args.Delta < 0)
  209. DownButton ();
  210. }
  211. protected virtual void OnChanged (object source, EventArgs e)
  212. {
  213. // Not clear, the docs state that this will raise the
  214. // Changed event, but that event is not listed anywhere.
  215. }
  216. protected override void OnFontChanged (EventArgs e)
  217. {
  218. base.OnFontChanged (e);
  219. entry.Font = Font;
  220. desired_height = entry.Height;
  221. Height = desired_height;
  222. }
  223. protected override void OnHandleCreated (EventArgs e)
  224. {
  225. base.OnHandleCreated (e);
  226. desired_height = entry.Height;
  227. }
  228. protected override void OnLayout (LayoutEventArgs args)
  229. {
  230. base.OnLayout (args);
  231. Rectangle bounds = Bounds;
  232. int entry_width = bounds.Right - scrollbar_button_size - 1;
  233. entry.SetBounds (bounds.X, bounds.Y, entry_width, bounds.Height);
  234. spinner.SetBounds (entry_width + 1, bounds.Y, scrollbar_button_size, bounds.Height);
  235. }
  236. protected override void OnPaint (PaintEventArgs e)
  237. {
  238. base.OnPaint (e);
  239. }
  240. protected override void SetVisibleCore (bool state)
  241. {
  242. base.SetVisibleCore (state);
  243. }
  244. protected override void WndProc (ref Message m)
  245. {
  246. base.WndProc (ref m);
  247. }
  248. protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
  249. {
  250. //
  251. // Force the size to be our height.
  252. //
  253. base.SetBoundsCore (x, y, width, desired_height, specified);
  254. }
  255. protected override void Dispose (bool disposing)
  256. {
  257. if (spinner != null){
  258. if (disposing){
  259. spinner.Dispose ();
  260. entry.Dispose ();
  261. }
  262. }
  263. spinner = null;
  264. entry = null;
  265. base.Dispose (true);
  266. }
  267. #endregion
  268. #region UpDownBase virtual methods
  269. //
  270. // These are hooked up to the various events from the Entry line that
  271. // we do not have yet, and implement the keyboard behavior (use a different
  272. // widget to test)
  273. //
  274. protected virtual void OnTextBoxKeyDown (object source, KeyEventArgs e)
  275. {
  276. }
  277. protected virtual void OnTextBoxKeyPress (object source, KeyPressEventArgs e)
  278. {
  279. }
  280. protected virtual void OnTextBoxLostFocus (object source, EventArgs e)
  281. {
  282. }
  283. protected virtual void OnTextBoxResize (object source, EventArgs e)
  284. {
  285. }
  286. protected virtual void OnTextBoxTextChanged (object source, EventArgs e)
  287. {
  288. }
  289. protected virtual void ValidateEditText ()
  290. {
  291. }
  292. #endregion
  293. #region UpDownBase standard methods
  294. public void Select (int start, int length)
  295. {
  296. // Selects text from start for lenght chars.
  297. }
  298. #endregion
  299. #region Abstract methods
  300. public abstract void DownButton ();
  301. public abstract void UpButton ();
  302. public abstract void UpdateEditText ();
  303. #endregion
  304. }
  305. }