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>
32 using System.Collections;
33 using System.ComponentModel;
35 using System.Runtime.InteropServices;
36 using System.Windows.Forms;
38 namespace System.Windows.Forms
40 [Designer("System.Windows.Forms.Design.UpDownBaseDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
41 public abstract class UpDownBase : System.Windows.Forms.ContainerControl {
42 #region UpDownSpinner Sub-class
43 internal sealed class UpDownSpinner : Control {
44 #region Local Variables
45 private const int InitialRepeatDelay = 50;
46 private UpDownBase owner;
47 private Timer tmrRepeat;
48 private Rectangle top_button_rect;
49 private Rectangle bottom_button_rect;
50 private int mouse_pressed;
53 private int repeat_delay;
54 private int repeat_counter;
55 #endregion // Local Variables
58 public UpDownSpinner(UpDownBase owner) {
63 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
64 this.SetStyle(ControlStyles.DoubleBuffer, true);
65 this.SetStyle(ControlStyles.Opaque, true);
66 this.SetStyle(ControlStyles.ResizeRedraw, true);
67 this.SetStyle(ControlStyles.UserPaint, true);
68 this.SetStyle(ControlStyles.Selectable, false);
69 this.SetStyle(ControlStyles.FixedHeight, true);
71 tmrRepeat = new Timer();
73 tmrRepeat.Enabled = false;
74 tmrRepeat.Interval = 10;
75 tmrRepeat.Tick += new EventHandler(tmrRepeat_Tick);
79 #endregion // Constructors
81 #region Private & Internal Methods
82 private void compute_rects() {
83 int top_button_height;
84 int bottom_button_height;
86 top_button_height = ClientSize.Height / 2;
87 bottom_button_height = ClientSize.Height - top_button_height;
89 top_button_rect = new Rectangle(0, 0, ClientSize.Width, top_button_height);
90 bottom_button_rect = new Rectangle(0, top_button_height, ClientSize.Width, bottom_button_height);
93 private void redraw(Graphics graphics) {
94 ButtonState top_button_state;
95 ButtonState bottom_button_state;
97 top_button_state = bottom_button_state = ButtonState.Normal;
99 if (mouse_pressed != 0) {
100 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y)) {
101 top_button_state = ButtonState.Pushed;
104 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y)) {
105 bottom_button_state = ButtonState.Pushed;
109 ControlPaint.DrawScrollButton(graphics, top_button_rect, ScrollButton.Up, top_button_state);
110 ControlPaint.DrawScrollButton(graphics, bottom_button_rect, ScrollButton.Down, bottom_button_state);
113 private void tmrRepeat_Tick(object sender, EventArgs e) {
114 if (repeat_delay > 1) {
117 if (repeat_counter < repeat_delay) {
122 repeat_delay = (repeat_delay * 3 / 4);
125 if (mouse_pressed == 0) {
126 tmrRepeat.Enabled = false;
129 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y)) {
133 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y)) {
137 #endregion // Private & Internal Methods
139 #region Protected Instance Methods
140 protected override void OnMouseDown(MouseEventArgs e) {
141 this.Select(owner.txtView);
143 if (e.Button != MouseButtons.Left) {
147 if (top_button_rect.Contains(e.X, e.Y)) {
150 } else if (bottom_button_rect.Contains(e.X, e.Y)) {
159 tmrRepeat.Enabled = true;
161 repeat_delay = InitialRepeatDelay;
166 protected override void OnMouseMove(MouseEventArgs e) {
167 ButtonState before, after;
169 before = ButtonState.Normal;
170 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y))
171 before = ButtonState.Pushed;
172 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y))
173 before = ButtonState.Pushed;
178 after = ButtonState.Normal;
179 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y))
180 after = ButtonState.Pushed;
181 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y))
182 after = ButtonState.Pushed;
184 if (before != after) {
185 if (after == ButtonState.Pushed) {
186 tmrRepeat.Enabled = true;
188 repeat_delay = InitialRepeatDelay;
190 // fire off one right now too for good luck
191 if (mouse_pressed == 1)
193 if (mouse_pressed == 2)
197 tmrRepeat.Enabled = false;
203 protected override void OnMouseUp(MouseEventArgs e) {
210 protected override void OnMouseWheel(MouseEventArgs e) {
213 else if (e.Delta < 0)
217 protected override void OnPaint(PaintEventArgs e) {
221 protected override void OnResize(EventArgs e) {
225 #endregion // Protected Instance Methods
227 #endregion // UpDownSpinner Sub-class
229 #region Local Variables
230 internal TextBox txtView;
231 private UpDownSpinner spnSpinner;
232 private bool _InterceptArrowKeys = true;
233 private LeftRightAlignment _UpDownAlign;
234 private bool changing_text;
235 private bool user_edit;
236 #endregion // Local Variables
238 #region Public Constructors
239 public UpDownBase() {
240 _UpDownAlign = LeftRightAlignment.Right;
241 border_style = BorderStyle.Fixed3D;
243 spnSpinner = new UpDownSpinner(this);
245 txtView = new FixedSizeTextBox(false, true);
246 txtView.ModifiedChanged += new EventHandler(OnChanged);
247 txtView.AcceptsReturn = true;
248 txtView.AutoSize = false;
249 txtView.BorderStyle = BorderStyle.None;
250 txtView.Location = new System.Drawing.Point(17, 17);
251 txtView.TabIndex = TabIndex;
254 Controls.Add (spnSpinner);
255 Controls.Add (txtView);
258 this.ActiveControl = txtView;
260 Height = PreferredHeight;
261 base.BackColor = txtView.BackColor;
263 GotFocus += new EventHandler (GotFocusHandler);
264 TabIndexChanged += new EventHandler (TabIndexChangedHandler);
266 txtView.MouseWheel += new MouseEventHandler(txtView_MouseWheel);
267 txtView.KeyDown += new KeyEventHandler(OnTextBoxKeyDown);
268 txtView.KeyPress += new KeyPressEventHandler(OnTextBoxKeyPress);
269 txtView.LostFocus += new EventHandler(OnTextBoxLostFocus);
270 txtView.Resize += new EventHandler(OnTextBoxResize);
271 txtView.TextChanged += new EventHandler(OnTextBoxTextChanged);
273 txtView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
275 SetStyle(ControlStyles.FixedHeight, true);
281 #region Private Methods
282 void reseat_controls() {
283 int text_displacement = 0;
285 int spinner_width = 16;
286 //int spinner_width = ClientSize.Height;
288 if (_UpDownAlign == LeftRightAlignment.Left) {
289 spnSpinner.Bounds = new Rectangle(0, 0, spinner_width, ClientSize.Height);
290 text_displacement = spnSpinner.Width;
292 spnSpinner.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left;
294 spnSpinner.Bounds = new Rectangle(ClientSize.Width - spinner_width, 0, spinner_width, ClientSize.Height);
296 spnSpinner.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right;
299 txtView.Bounds = new Rectangle(text_displacement, 0, ClientSize.Width - spinner_width, Height);
302 private void txtView_MouseWheel(object sender, MouseEventArgs e) {
305 } else if (e.Delta < 0) {
310 private void GotFocusHandler (object sender, EventArgs e)
315 private void TabIndexChangedHandler (object sender, EventArgs e)
317 txtView.TabIndex = TabIndex;
320 internal override void OnPaintInternal (PaintEventArgs e) {
321 e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), ClientRectangle);
323 #endregion // Private Methods
325 #region Public Instance Properties
327 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
328 [EditorBrowsable(EditorBrowsableState.Never)]
329 public override bool AutoScroll {
331 return base.AutoScroll;
335 base.AutoScroll = value;
340 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
341 [EditorBrowsable(EditorBrowsableState.Never)]
342 public Size AutoScrollMargin {
344 return base.AutoScrollMargin;
348 base.AutoScrollMargin = value;
353 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
354 [EditorBrowsable(EditorBrowsableState.Never)]
355 public Size AutoScrollMinSize {
357 return base.AutoScrollMinSize;
361 base.AutoScrollMinSize = value;
365 public override Color BackColor {
367 return base.BackColor;
371 base.BackColor = value;
372 txtView.BackColor = value;
377 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
378 [EditorBrowsable(EditorBrowsableState.Never)]
379 public override Image BackgroundImage {
381 return base.BackgroundImage;
384 base.BackgroundImage = value;
385 txtView.BackgroundImage = value;
390 [DefaultValue(BorderStyle.Fixed3D)]
392 public BorderStyle BorderStyle {
393 get { return InternalBorderStyle; }
394 set { InternalBorderStyle = value; }
397 public override ContextMenu ContextMenu {
399 return base.ContextMenu;
402 base.ContextMenu = value;
403 txtView.ContextMenu = value;
404 spnSpinner.ContextMenu = value;
409 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
410 [EditorBrowsable(EditorBrowsableState.Never)]
411 public DockPaddingEdges DockPadding {
413 return base.DockPadding;
418 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
419 public override bool Focused {
421 return txtView.Focused;
425 public override Color ForeColor {
427 return base.ForeColor;
430 base.ForeColor = value;
431 txtView.ForeColor = value;
436 public bool InterceptArrowKeys {
438 return _InterceptArrowKeys;
441 _InterceptArrowKeys = value;
446 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
447 [EditorBrowsable(EditorBrowsableState.Advanced)]
448 public int PreferredHeight {
450 // For some reason, the TextBox's PreferredHeight does not
451 // change when the Font property is assigned. Without a
452 // border, it will always be Font.Height anyway.
453 //int text_box_preferred_height = (txtView != null) ? txtView.PreferredHeight : Font.Height;
454 int text_box_preferred_height = Font.Height;
456 switch (border_style) {
457 case BorderStyle.FixedSingle:
458 case BorderStyle.Fixed3D:
459 text_box_preferred_height += 3; // magic number? :-)
461 return text_box_preferred_height + 4;
463 case BorderStyle.None:
465 return text_box_preferred_height;
470 [DefaultValue(false)]
471 public bool ReadOnly {
473 return txtView.ReadOnly;
476 txtView.ReadOnly = value;
481 public override string Text {
483 if (txtView != null) {
489 bool suppress_validation = changing_text;
491 txtView.Text = value;
493 if (!suppress_validation)
498 [DefaultValue(HorizontalAlignment.Left)]
500 public HorizontalAlignment TextAlign {
502 return txtView.TextAlign;
505 txtView.TextAlign = value;
509 [DefaultValue(LeftRightAlignment.Right)]
511 public LeftRightAlignment UpDownAlign {
516 _UpDownAlign = value;
521 #endregion // Public Instance Properties
523 #region Protected Instance Properties
524 protected bool ChangingText {
526 return changing_text;
529 changing_text = value;
533 protected override CreateParams CreateParams {
535 return base.CreateParams;
539 protected override Size DefaultSize {
541 return new Size(120, this.PreferredHeight);
545 protected bool UserEdit {
553 #endregion // Protected Instance Properties
555 #region Public Instance Methods
556 public abstract void DownButton();
557 public void Select(int start, int length) {
558 txtView.Select(start, length);
561 public abstract void UpButton();
562 #endregion // Public Instance Methods
564 #region Protected Instance Methods
565 protected override void Dispose(bool disposing) {
570 spnSpinner.Dispose();
573 base.Dispose (disposing);
576 protected virtual void OnChanged(object source, EventArgs e) {
579 protected override void OnFontChanged(EventArgs e) {
580 txtView.Font = this.Font;
581 Height = PreferredHeight;
584 protected override void OnHandleCreated(EventArgs e) {
585 base.OnHandleCreated (e);
588 protected override void OnLayout(LayoutEventArgs e) {
592 protected override void OnMouseWheel(MouseEventArgs e) {
593 // prevent this event from firing twice for the same mouse action!
594 if (GetChildAtPoint(new Point(e.X, e.Y)) == null)
595 txtView_MouseWheel(null, e);
598 protected virtual void OnTextBoxKeyDown(object source, KeyEventArgs e) {
599 if (_InterceptArrowKeys) {
600 if ((e.KeyCode == Keys.Up) || (e.KeyCode == Keys.Down)) {
603 if (e.KeyCode == Keys.Up)
605 if (e.KeyCode == Keys.Down)
613 protected virtual void OnTextBoxKeyPress(object source, KeyPressEventArgs e) {
614 if (e.KeyChar == '\r') {
621 protected virtual void OnTextBoxLostFocus(object source, EventArgs e) {
627 protected virtual void OnTextBoxResize(object source, EventArgs e) {
628 // compute the new height, taking the border into account
629 Height = PreferredHeight;
631 // let anchoring reposition the controls
634 protected virtual void OnTextBoxTextChanged(object source, EventArgs e) {
636 ChangingText = false;
644 protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
645 base.SetBoundsCore(x, y, width, height, specified);
647 if ((specified & BoundsSpecified.Size) != BoundsSpecified.None) {
652 protected abstract void UpdateEditText();
654 protected virtual void ValidateEditText() {
655 // to be overridden by subclassers
658 [EditorBrowsable(EditorBrowsableState.Advanced)]
659 protected override void WndProc(ref Message m) {
660 base.WndProc (ref m);
662 #endregion // Protected Instance Methods
666 [EditorBrowsable(EditorBrowsableState.Never)]
667 public new event EventHandler BackgroundImageChanged {
668 add { base.BackgroundImageChanged += value; }
669 remove { base.BackgroundImageChanged -= value; }
673 [EditorBrowsable(EditorBrowsableState.Never)]
674 public new event EventHandler MouseEnter {
675 add { base.MouseEnter += value; }
676 remove { base.MouseEnter -= value; }
680 [EditorBrowsable(EditorBrowsableState.Never)]
681 public new event EventHandler MouseHover {
682 add { base.MouseHover += value; }
683 remove { base.MouseHover -= value; }
687 [EditorBrowsable(EditorBrowsableState.Never)]
688 public new event EventHandler MouseLeave {
689 add { base.MouseLeave += value; }
690 remove { base.MouseLeave -= value; }
694 [EditorBrowsable(EditorBrowsableState.Never)]
695 public new event MouseEventHandler MouseMove {
696 add { base.MouseMove += value; }
697 remove { base.MouseMove -= value; }