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);
70 tmrRepeat = new Timer();
72 tmrRepeat.Enabled = false;
73 tmrRepeat.Interval = 10;
74 tmrRepeat.Tick += new EventHandler(tmrRepeat_Tick);
78 #endregion // Constructors
80 #region Private & Internal Methods
81 private void compute_rects() {
82 int top_button_height;
83 int bottom_button_height;
85 top_button_height = ClientSize.Height / 2;
86 bottom_button_height = ClientSize.Height - top_button_height;
88 top_button_rect = new Rectangle(0, 0, ClientSize.Width, top_button_height);
89 bottom_button_rect = new Rectangle(0, top_button_height, ClientSize.Width, bottom_button_height);
92 private void redraw(Graphics graphics) {
93 ButtonState top_button_state;
94 ButtonState bottom_button_state;
96 top_button_state = bottom_button_state = ButtonState.Normal;
98 if (mouse_pressed != 0) {
99 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y)) {
100 top_button_state = ButtonState.Pushed;
103 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y)) {
104 bottom_button_state = ButtonState.Pushed;
108 ControlPaint.DrawScrollButton(graphics, top_button_rect, ScrollButton.Up, top_button_state);
109 ControlPaint.DrawScrollButton(graphics, bottom_button_rect, ScrollButton.Down, bottom_button_state);
112 private void tmrRepeat_Tick(object sender, EventArgs e) {
113 if (repeat_delay > 1) {
116 if (repeat_counter < repeat_delay) {
121 repeat_delay = (repeat_delay * 3 / 4);
124 if (mouse_pressed == 0) {
125 tmrRepeat.Enabled = false;
128 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y)) {
132 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y)) {
136 #endregion // Private & Internal Methods
138 #region Protected Instance Methods
139 protected override void OnMouseDown(MouseEventArgs e) {
140 this.Select(owner.txtView);
142 if (e.Button != MouseButtons.Left) {
146 if (top_button_rect.Contains(e.X, e.Y)) {
149 } else if (bottom_button_rect.Contains(e.X, e.Y)) {
158 tmrRepeat.Enabled = true;
160 repeat_delay = InitialRepeatDelay;
162 using (Graphics g = CreateGraphics()) {
167 protected override void OnMouseMove(MouseEventArgs e) {
168 ButtonState before, after;
170 before = ButtonState.Normal;
171 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y))
172 before = ButtonState.Pushed;
173 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y))
174 before = ButtonState.Pushed;
179 after = ButtonState.Normal;
180 if ((mouse_pressed == 1) && top_button_rect.Contains(mouse_x, mouse_y))
181 after = ButtonState.Pushed;
182 if ((mouse_pressed == 2) && bottom_button_rect.Contains(mouse_x, mouse_y))
183 after = ButtonState.Pushed;
185 if (before != after) {
186 if (after == ButtonState.Pushed) {
187 tmrRepeat.Enabled = true;
189 repeat_delay = InitialRepeatDelay;
191 // fire off one right now too for good luck
192 if (mouse_pressed == 1)
194 if (mouse_pressed == 2)
198 tmrRepeat.Enabled = false;
200 using (Graphics g = CreateGraphics()) {
206 protected override void OnMouseUp(MouseEventArgs e) {
210 using (Graphics g = CreateGraphics()) {
215 protected override void OnMouseWheel(MouseEventArgs e) {
218 else if (e.Delta < 0)
222 protected override void OnPaint(PaintEventArgs e) {
226 protected override void OnResize(EventArgs e) {
230 #endregion // Protected Instance Methods
232 #endregion // UpDownSpinner Sub-class
234 #region Local Variables
235 internal TextBox txtView;
236 private UpDownSpinner spnSpinner;
237 private bool _InterceptArrowKeys = true;
238 private LeftRightAlignment _UpDownAlign;
239 private bool changing_text;
240 private bool user_edit;
241 #endregion // Local Variables
243 #region Public Constructors
244 public UpDownBase() {
245 _UpDownAlign = LeftRightAlignment.Right;
246 border_style = BorderStyle.Fixed3D;
248 spnSpinner = new UpDownSpinner(this);
250 txtView = new TextBox();
251 txtView.ModifiedChanged += new EventHandler(OnChanged);
252 txtView.AcceptsReturn = true;
253 txtView.AutoSize = false;
254 txtView.BorderStyle = BorderStyle.None;
255 txtView.Location = new System.Drawing.Point(17, 17);
256 txtView.TabIndex = 0;
259 Controls.AddImplicit (txtView);
260 Controls.AddImplicit (spnSpinner);
263 this.ActiveControl = txtView;
265 Height = PreferredHeight;
266 base.BackColor = txtView.BackColor;
268 txtView.MouseWheel += new MouseEventHandler(txtView_MouseWheel);
270 txtView.KeyDown += new KeyEventHandler(OnTextBoxKeyDown);
271 txtView.KeyPress += new KeyPressEventHandler(OnTextBoxKeyPress);
272 txtView.LostFocus += new EventHandler(OnTextBoxLostFocus);
273 txtView.Resize += new EventHandler(OnTextBoxResize);
274 txtView.TextChanged += new EventHandler(OnTextBoxTextChanged);
276 txtView.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
277 this.Paint +=new PaintEventHandler(UpDownBase_Paint);
279 SetStyle(ControlStyles.FixedHeight, true);
285 #region Private Methods
286 void reseat_controls() {
287 int text_displacement = 0;
289 int spinner_width = 16;
290 //int spinner_width = ClientSize.Height;
292 if (_UpDownAlign == LeftRightAlignment.Left) {
293 spnSpinner.Bounds = new Rectangle(0, 0, spinner_width, ClientSize.Height);
294 text_displacement = spnSpinner.Width;
296 spnSpinner.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left;
298 spnSpinner.Bounds = new Rectangle(ClientSize.Width - spinner_width, 0, spinner_width, ClientSize.Height);
300 spnSpinner.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right;
303 txtView.Bounds = new Rectangle(text_displacement, 0, ClientSize.Width - spinner_width, Height);
306 private void txtView_MouseWheel(object sender, MouseEventArgs e) {
309 } else if (e.Delta < 0) {
315 private void UpDownBase_Paint(object sender, PaintEventArgs e) {
316 e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), ClientRectangle);
318 #endregion // Private Methods
320 #region Public Instance Properties
322 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
323 [EditorBrowsable(EditorBrowsableState.Never)]
324 public override bool AutoScroll {
326 return base.AutoScroll;
330 base.AutoScroll = value;
335 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
336 [EditorBrowsable(EditorBrowsableState.Never)]
337 public Size AutoScrollMargin {
339 return base.AutoScrollMargin;
343 base.AutoScrollMargin = value;
348 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
349 [EditorBrowsable(EditorBrowsableState.Never)]
350 public Size AutoScrollMinSize {
352 return base.AutoScrollMinSize;
356 base.AutoScrollMinSize = value;
360 public override Color BackColor {
362 return base.BackColor;
366 base.BackColor = value;
367 txtView.BackColor = value;
372 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
373 [EditorBrowsable(EditorBrowsableState.Never)]
374 public override Image BackgroundImage {
376 return base.BackgroundImage;
379 base.BackgroundImage = value;
380 txtView.BackgroundImage = value;
385 [DefaultValue(BorderStyle.Fixed3D)]
387 public BorderStyle BorderStyle {
388 get { return InternalBorderStyle; }
389 set { InternalBorderStyle = value; }
392 public override ContextMenu ContextMenu {
394 return base.ContextMenu;
397 base.ContextMenu = value;
398 txtView.ContextMenu = value;
399 spnSpinner.ContextMenu = value;
404 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
405 [EditorBrowsable(EditorBrowsableState.Never)]
406 public DockPaddingEdges DockPadding {
408 return base.DockPadding;
413 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
414 public override bool Focused {
416 return txtView.Focused;
420 public override Color ForeColor {
422 return base.ForeColor;
425 base.ForeColor = value;
426 txtView.ForeColor = value;
431 public bool InterceptArrowKeys {
433 return _InterceptArrowKeys;
436 _InterceptArrowKeys = value;
441 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
442 [EditorBrowsable(EditorBrowsableState.Advanced)]
443 public int PreferredHeight {
445 // For some reason, the TextBox's PreferredHeight does not
446 // change when the Font property is assigned. Without a
447 // border, it will always be Font.Height anyway.
448 //int text_box_preferred_height = (txtView != null) ? txtView.PreferredHeight : Font.Height;
449 int text_box_preferred_height = Font.Height;
451 switch (border_style) {
452 case BorderStyle.FixedSingle:
453 case BorderStyle.Fixed3D:
454 text_box_preferred_height += 3; // magic number? :-)
456 return text_box_preferred_height + 4;
458 case BorderStyle.None:
460 return text_box_preferred_height;
465 [DefaultValue(false)]
466 public bool ReadOnly {
468 return txtView.ReadOnly;
471 txtView.ReadOnly = value;
476 public override string Text {
481 bool suppress_validation = changing_text;
483 txtView.Text = value;
485 if (!suppress_validation)
490 [DefaultValue(HorizontalAlignment.Left)]
492 public HorizontalAlignment TextAlign {
494 return txtView.TextAlign;
497 txtView.TextAlign = value;
501 [DefaultValue(LeftRightAlignment.Right)]
503 public LeftRightAlignment UpDownAlign {
508 _UpDownAlign = value;
513 #endregion // Public Instance Properties
515 #region Protected Instance Properties
516 protected bool ChangingText {
518 return changing_text;
521 changing_text = value;
525 protected override CreateParams CreateParams {
527 return base.CreateParams;
531 protected override Size DefaultSize {
533 return new Size(120, this.PreferredHeight);
537 protected bool UserEdit {
545 #endregion // Protected Instance Properties
547 #region Public Instance Methods
548 public abstract void DownButton();
549 public void Select(int start, int length) {
550 txtView.Select(start, length);
553 public abstract void UpButton();
554 #endregion // Public Instance Methods
556 #region Protected Instance Methods
557 protected override void Dispose(bool disposing) {
562 spnSpinner.Dispose();
565 base.Dispose (disposing);
569 protected virtual void OnChanged(object source, EventArgs e) {
573 protected override void OnFontChanged(EventArgs e) {
574 txtView.Font = this.Font;
575 Height = PreferredHeight;
578 protected override void OnHandleCreated(EventArgs e) {
579 base.OnHandleCreated (e);
582 protected override void OnLayout(LayoutEventArgs e) {
586 protected override void OnMouseWheel(MouseEventArgs e) {
587 // prevent this event from firing twice for the same mouse action!
588 if (GetChildAtPoint(new Point(e.X, e.Y)) == null)
589 txtView_MouseWheel(null, e);
592 protected virtual void OnTextBoxKeyDown(object source, KeyEventArgs e) {
593 if (_InterceptArrowKeys) {
594 if ((e.KeyCode == Keys.Up) || (e.KeyCode == Keys.Down)) {
597 if (e.KeyCode == Keys.Up)
599 if (e.KeyCode == Keys.Down)
607 protected virtual void OnTextBoxKeyPress(object source, KeyPressEventArgs e) {
608 if (e.KeyChar == '\r') {
615 protected virtual void OnTextBoxLostFocus(object source, EventArgs e) {
621 protected virtual void OnTextBoxResize(object source, EventArgs e) {
622 // compute the new height, taking the border into account
623 Height = PreferredHeight;
625 // let anchoring reposition the controls
628 protected virtual void OnTextBoxTextChanged(object source, EventArgs e) {
630 ChangingText = false;
638 protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
639 base.SetBoundsCore(x, y, width, height, specified);
641 if ((specified & BoundsSpecified.Size) != BoundsSpecified.None) {
646 protected abstract void UpdateEditText();
648 protected virtual void ValidateEditText() {
649 // to be overridden by subclassers
652 [EditorBrowsable(EditorBrowsableState.Advanced)]
653 protected override void WndProc(ref Message m) {
654 base.WndProc (ref m);
656 #endregion // Protected Instance Methods
660 [EditorBrowsable(EditorBrowsableState.Never)]
661 public new event EventHandler BackgroundImageChanged;
664 [EditorBrowsable(EditorBrowsableState.Never)]
665 public new event EventHandler MouseEnter;
668 [EditorBrowsable(EditorBrowsableState.Never)]
669 public new event EventHandler MouseHover;
672 [EditorBrowsable(EditorBrowsableState.Never)]
673 public new event EventHandler MouseLeave;
676 [EditorBrowsable(EditorBrowsableState.Never)]
677 public new event MouseEventHandler MouseMove;