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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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) 2005 Novell, Inc.
23 // Jonathan Gilbert <logic@deltaq.org>
25 // Integration into MWF:
26 // Peter Bartok <pbartok@novell.com>
30 using System.Collections;
31 using System.ComponentModel;
33 using System.Runtime.InteropServices;
34 using System.Windows.Forms;
36 namespace System.Windows.Forms
39 [ClassInterface (ClassInterfaceType.AutoDispatch)]
42 [Designer("System.Windows.Forms.Design.UpDownBaseDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
43 public abstract class UpDownBase : ContainerControl {
44 #region UpDownSpinner Sub-class
45 internal sealed class UpDownSpinner : Control {
46 #region Local Variables
47 private const int InitialRepeatDelay = 50;
48 private UpDownBase owner;
49 private Timer tmrRepeat;
50 private Rectangle top_button_rect;
51 private Rectangle bottom_button_rect;
52 private int mouse_pressed;
55 private int repeat_delay;
56 private int repeat_counter;
57 #endregion // Local Variables
60 public UpDownSpinner(UpDownBase owner)
66 SetStyle(ControlStyles.AllPaintingInWmPaint, true);
67 SetStyle(ControlStyles.DoubleBuffer, true);
68 SetStyle(ControlStyles.Opaque, true);
69 SetStyle(ControlStyles.ResizeRedraw, true);
70 SetStyle(ControlStyles.UserPaint, true);
71 SetStyle(ControlStyles.FixedHeight, true);
72 SetStyle(ControlStyles.Selectable, false);
74 tmrRepeat = new Timer();
76 tmrRepeat.Enabled = false;
77 tmrRepeat.Interval = 10;
78 tmrRepeat.Tick += new EventHandler(tmrRepeat_Tick);
82 #endregion // Constructors
84 #region Private & Internal Methods
85 private void compute_rects ()
87 int top_button_height;
88 int bottom_button_height;
90 top_button_height = ClientSize.Height / 2;
91 bottom_button_height = ClientSize.Height - top_button_height;
93 top_button_rect = new Rectangle(0, 0, ClientSize.Width, top_button_height);
94 bottom_button_rect = new Rectangle(0, top_button_height, ClientSize.Width, bottom_button_height);
97 private void redraw (Graphics graphics)
99 ButtonState top_button_state;
100 ButtonState bottom_button_state;
102 top_button_state = bottom_button_state = ButtonState.Normal;
104 if (mouse_pressed != 0) {
105 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y)) {
106 top_button_state = ButtonState.Pushed;
109 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y)) {
110 bottom_button_state = ButtonState.Pushed;
114 ControlPaint.DrawScrollButton(graphics, top_button_rect, ScrollButton.Up, top_button_state);
115 ControlPaint.DrawScrollButton(graphics, bottom_button_rect, ScrollButton.Down, bottom_button_state);
118 private void tmrRepeat_Tick (object sender, EventArgs e)
120 if (repeat_delay > 1) {
123 if (repeat_counter < repeat_delay) {
128 repeat_delay = (repeat_delay * 3 / 4);
131 if (mouse_pressed == 0) {
132 tmrRepeat.Enabled = false;
135 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y)) {
139 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y)) {
143 #endregion // Private & Internal Methods
145 #region Protected Instance Methods
146 protected override void OnMouseDown (MouseEventArgs e)
148 if (e.Button != MouseButtons.Left) {
152 if (top_button_rect.Contains(e.X, e.Y)) {
155 } else if (bottom_button_rect.Contains(e.X, e.Y)) {
164 tmrRepeat.Enabled = true;
166 repeat_delay = InitialRepeatDelay;
171 protected override void OnMouseMove (MouseEventArgs e)
173 ButtonState before, after;
175 before = ButtonState.Normal;
176 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y))
177 before = ButtonState.Pushed;
178 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y))
179 before = ButtonState.Pushed;
184 after = ButtonState.Normal;
185 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y))
186 after = ButtonState.Pushed;
187 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y))
188 after = ButtonState.Pushed;
190 if (before != after) {
191 if (after == ButtonState.Pushed) {
192 tmrRepeat.Enabled = true;
194 repeat_delay = InitialRepeatDelay;
196 // fire off one right now too for good luck
197 if (mouse_pressed == 1)
199 if (mouse_pressed == 2)
203 tmrRepeat.Enabled = false;
209 protected override void OnMouseUp(MouseEventArgs e)
217 protected override void OnMouseWheel(MouseEventArgs e)
221 else if (e.Delta < 0)
225 protected override void OnPaint(PaintEventArgs e)
230 protected override void OnResize(EventArgs e)
235 #endregion // Protected Instance Methods
237 #endregion // UpDownSpinner Sub-class
239 internal class UpDownTextBox : TextBox {
241 private UpDownBase owner;
243 public UpDownTextBox (UpDownBase owner)
247 SetStyle (ControlStyles.FixedWidth, false);
248 SetStyle (ControlStyles.Selectable, false);
252 // The following can be shown to be present by
253 // adding events to both the UpDown and the
254 // internal textbox. the textbox doesn't
255 // generate any, and the updown generates them
257 protected override void OnGotFocus (EventArgs e)
259 ShowSelection = true;
260 owner.OnGotFocus (e);
264 protected override void OnLostFocus (EventArgs e)
266 ShowSelection = false;
267 owner.OnLostFocus (e);
271 protected override void OnMouseDown (MouseEventArgs e)
273 // XXX look into whether or not the
274 // mouse event args are altered in
277 owner.OnMouseDown (e);
281 protected override void OnMouseUp (MouseEventArgs e)
283 // XXX look into whether or not the
284 // mouse event args are altered in
291 // XXX there are likely more events that forward up to the UpDown
294 #region Local Variables
295 internal UpDownTextBox txtView;
296 private UpDownSpinner spnSpinner;
297 private bool _InterceptArrowKeys = true;
298 private LeftRightAlignment _UpDownAlign;
299 private bool changing_text;
300 private bool user_edit;
301 #endregion // Local Variables
303 #region Public Constructors
306 _UpDownAlign = LeftRightAlignment.Right;
307 InternalBorderStyle = BorderStyle.Fixed3D;
309 spnSpinner = new UpDownSpinner(this);
311 txtView = new UpDownTextBox (this);
312 txtView.ModifiedChanged += new EventHandler(OnChanged);
313 txtView.AcceptsReturn = true;
314 txtView.AutoSize = false;
315 txtView.BorderStyle = BorderStyle.None;
316 txtView.Location = new System.Drawing.Point(17, 17);
317 txtView.TabIndex = TabIndex;
319 spnSpinner.Width = 16;
320 spnSpinner.Dock = DockStyle.Right;
322 txtView.Dock = DockStyle.Fill;
325 Controls.Add (txtView);
326 Controls.Add (spnSpinner);
329 Height = PreferredHeight;
330 base.BackColor = txtView.BackColor;
332 TabIndexChanged += new EventHandler (TabIndexChangedHandler);
334 txtView.KeyDown += new KeyEventHandler(OnTextBoxKeyDown);
335 txtView.KeyPress += new KeyPressEventHandler(OnTextBoxKeyPress);
336 // txtView.LostFocus += new EventHandler(OnTextBoxLostFocus);
337 txtView.Resize += new EventHandler(OnTextBoxResize);
338 txtView.TextChanged += new EventHandler(OnTextBoxTextChanged);
340 // So the child controls don't get auto selected when the updown is selected
341 auto_select_child = false;
342 SetStyle(ControlStyles.FixedHeight, true);
343 SetStyle(ControlStyles.Selectable, true);
345 SetStyle (ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
346 SetStyle (ControlStyles.StandardClick | ControlStyles.UseTextForAccessibility, false);
351 #region Private Methods
352 private void TabIndexChangedHandler (object sender, EventArgs e)
354 txtView.TabIndex = TabIndex;
357 internal override void OnPaintInternal (PaintEventArgs e)
359 e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), ClientRectangle);
362 #endregion // Private Methods
364 #region Public Instance Properties
366 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
367 [EditorBrowsable(EditorBrowsableState.Never)]
368 public override bool AutoScroll {
370 return base.AutoScroll;
374 base.AutoScroll = value;
379 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
380 [EditorBrowsable(EditorBrowsableState.Never)]
381 public new Size AutoScrollMargin {
382 get { return base.AutoScrollMargin; }
383 set { base.AutoScrollMargin = value; }
387 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
388 [EditorBrowsable(EditorBrowsableState.Never)]
389 public new Size AutoScrollMinSize {
390 get { return base.AutoScrollMinSize; }
391 set { base.AutoScrollMinSize = value; }
396 [EditorBrowsable (EditorBrowsableState.Always)]
397 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
398 public override bool AutoSize {
399 get { return base.AutoSize; }
400 set { base.AutoSize = value; }
404 public override Color BackColor {
406 return base.BackColor;
410 base.BackColor = value;
411 txtView.BackColor = value;
416 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
417 [EditorBrowsable(EditorBrowsableState.Never)]
418 public override Image BackgroundImage {
420 return base.BackgroundImage;
423 base.BackgroundImage = value;
424 txtView.BackgroundImage = value;
430 [EditorBrowsable (EditorBrowsableState.Never)]
431 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
432 public override ImageLayout BackgroundImageLayout {
433 get { return base.BackgroundImageLayout; }
434 set { base.BackgroundImageLayout = value; }
438 [DefaultValue(BorderStyle.Fixed3D)]
440 public BorderStyle BorderStyle {
441 get { return InternalBorderStyle; }
442 set { InternalBorderStyle = value; }
445 public override ContextMenu ContextMenu {
447 return base.ContextMenu;
450 base.ContextMenu = value;
451 txtView.ContextMenu = value;
452 spnSpinner.ContextMenu = value;
457 public override ContextMenuStrip ContextMenuStrip {
458 get { return base.ContextMenuStrip; }
460 base.ContextMenuStrip = value;
461 txtView.ContextMenuStrip = value;
462 spnSpinner.ContextMenuStrip = value;
468 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
469 [EditorBrowsable(EditorBrowsableState.Never)]
470 public new DockPaddingEdges DockPadding {
471 get { return base.DockPadding; }
475 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
476 public override bool Focused {
478 return txtView.Focused;
482 public override Color ForeColor {
484 return base.ForeColor;
487 base.ForeColor = value;
488 txtView.ForeColor = value;
493 public bool InterceptArrowKeys {
495 return _InterceptArrowKeys;
498 _InterceptArrowKeys = value;
503 public override Size MaximumSize {
504 get { return base.MaximumSize; }
505 set { base.MaximumSize = new Size (value.Width, 0); }
508 public override Size MinimumSize {
509 get { return base.MinimumSize; }
510 set { base.MinimumSize = new Size (value.Width, 0); }
515 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
516 [EditorBrowsable(EditorBrowsableState.Advanced)]
517 public int PreferredHeight {
519 // For some reason, the TextBox's PreferredHeight does not
520 // change when the Font property is assigned. Without a
521 // border, it will always be Font.Height anyway.
522 //int text_box_preferred_height = (txtView != null) ? txtView.PreferredHeight : Font.Height;
523 int text_box_preferred_height = Font.Height;
525 switch (border_style) {
526 case BorderStyle.FixedSingle:
527 case BorderStyle.Fixed3D:
528 text_box_preferred_height += 3; // magic number? :-)
530 return text_box_preferred_height + 4;
532 case BorderStyle.None:
534 return text_box_preferred_height;
539 [DefaultValue(false)]
540 public bool ReadOnly {
542 return txtView.ReadOnly;
545 txtView.ReadOnly = value;
550 public override string Text {
552 if (txtView != null) {
558 txtView.Text = value;
562 txtView.SelectionLength = 0;
566 [DefaultValue(HorizontalAlignment.Left)]
568 public HorizontalAlignment TextAlign {
570 return txtView.TextAlign;
573 txtView.TextAlign = value;
577 [DefaultValue(LeftRightAlignment.Right)]
579 public LeftRightAlignment UpDownAlign {
584 if (_UpDownAlign != value) {
585 _UpDownAlign = value;
587 if (value == LeftRightAlignment.Left)
588 spnSpinner.Dock = DockStyle.Left;
590 spnSpinner.Dock = DockStyle.Right;
594 #endregion // Public Instance Properties
596 #region Protected Instance Properties
597 protected bool ChangingText {
599 return changing_text;
602 changing_text = value;
606 protected override CreateParams CreateParams {
608 return base.CreateParams;
612 protected override Size DefaultSize {
614 return new Size(120, this.PreferredHeight);
618 protected bool UserEdit {
626 #endregion // Protected Instance Properties
628 #region Public Instance Methods
629 public abstract void DownButton ();
630 public void Select(int start, int length)
632 txtView.Select(start, length);
635 public abstract void UpButton ();
636 #endregion // Public Instance Methods
638 #region Protected Instance Methods
640 protected override void Dispose (bool disposing)
646 spnSpinner.Dispose();
649 base.Dispose (disposing);
653 protected virtual void OnChanged (object source, EventArgs e)
657 protected override void OnFontChanged (EventArgs e)
659 txtView.Font = this.Font;
660 Height = PreferredHeight;
663 protected override void OnHandleCreated (EventArgs e)
665 base.OnHandleCreated (e);
669 protected override void OnHandleDestroyed (EventArgs e)
671 base.OnHandleDestroyed (e);
675 protected override void OnLayout (LayoutEventArgs e)
681 protected override void OnMouseDown (MouseEventArgs e)
683 base.OnMouseDown (e);
686 protected override void OnMouseUp (MouseEventArgs e)
692 protected override void OnMouseWheel (MouseEventArgs e)
696 else if (e.Delta < 0)
701 protected override void OnPaint (PaintEventArgs e)
707 protected virtual void OnTextBoxKeyDown (object source, KeyEventArgs e)
709 if (_InterceptArrowKeys) {
710 if ((e.KeyCode == Keys.Up) || (e.KeyCode == Keys.Down)) {
713 if (e.KeyCode == Keys.Up)
715 if (e.KeyCode == Keys.Down)
723 protected virtual void OnTextBoxKeyPress (object source, KeyPressEventArgs e)
725 if (e.KeyChar == '\r') {
732 protected virtual void OnTextBoxLostFocus (object source, EventArgs e)
739 protected virtual void OnTextBoxResize (object source, EventArgs e)
741 // compute the new height, taking the border into account
742 Height = PreferredHeight;
744 // let anchoring reposition the controls
747 protected virtual void OnTextBoxTextChanged (object source, EventArgs e)
750 ChangingText = false;
758 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
760 base.SetBoundsCore(x, y, width, height, specified);
764 protected abstract void UpdateEditText ();
766 protected virtual void ValidateEditText ()
768 // to be overridden by subclassers
771 [EditorBrowsable(EditorBrowsableState.Advanced)]
772 protected override void WndProc (ref Message m)
774 switch((Msg) m.Msg) {
778 XplatUI.SendMessage (txtView.Handle, (Msg) m.Msg, m.WParam, m.LParam);
780 case Msg.WM_SETFOCUS:
781 ActiveControl = txtView;
783 case Msg.WM_KILLFOCUS:
784 ActiveControl = null;
787 base.WndProc (ref m);
791 #endregion // Protected Instance Methods
796 [EditorBrowsable (EditorBrowsableState.Always)]
797 public new event EventHandler AutoSizeChanged {
798 add { base.AutoSizeChanged += value; }
799 remove { base.AutoSizeChanged -= value; }
804 [EditorBrowsable(EditorBrowsableState.Never)]
805 public new event EventHandler BackgroundImageChanged {
806 add { base.BackgroundImageChanged += value; }
807 remove { base.BackgroundImageChanged -= value; }
812 [EditorBrowsable (EditorBrowsableState.Never)]
813 public new event EventHandler BackgroundImageLayoutChanged {
814 add { base.BackgroundImageLayoutChanged += value; }
815 remove { base.BackgroundImageLayoutChanged -= value; }
820 [EditorBrowsable(EditorBrowsableState.Never)]
821 public new event EventHandler MouseEnter {
822 add { base.MouseEnter += value; }
823 remove { base.MouseEnter -= value; }
827 [EditorBrowsable(EditorBrowsableState.Never)]
828 public new event EventHandler MouseHover {
829 add { base.MouseHover += value; }
830 remove { base.MouseHover -= value; }
834 [EditorBrowsable(EditorBrowsableState.Never)]
835 public new event EventHandler MouseLeave {
836 add { base.MouseLeave += value; }
837 remove { base.MouseLeave -= value; }
841 [EditorBrowsable(EditorBrowsableState.Never)]
842 public new event MouseEventHandler MouseMove {
843 add { base.MouseMove += value; }
844 remove { base.MouseMove -= value; }