2009-12-07 Rolf Bjarne Kvinge <RKvinge@novell.com>
[moon.git] / class / System.Windows / System.Windows.Controls / TextBox.cs
blob1f73c364141944964d9a7426d9dca2a38ef5d370
1 //
2 // Contact:
3 // Moonlight List (moonlight-list@lists.ximian.com)
4 //
5 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 using Mono;
28 using System.Windows;
29 using System.Windows.Automation;
30 using System.Windows.Automation.Peers;
31 using System.Windows.Input;
32 using System.Windows.Media;
33 using System.Windows.Documents;
34 using System.Collections.Generic;
36 namespace System.Windows.Controls {
38 [TemplateVisualStateAttribute (Name = "Disabled", GroupName = "CommonStates")]
39 [TemplateVisualStateAttribute (Name = "Normal", GroupName = "CommonStates")]
40 [TemplateVisualStateAttribute (Name = "MouseOver", GroupName = "CommonStates")]
41 [TemplateVisualStateAttribute (Name = "ReadOnly", GroupName = "CommonStates")]
42 [TemplateVisualStateAttribute (Name = "Focused", GroupName = "FocusStates")]
43 [TemplateVisualStateAttribute (Name = "Unfocused", GroupName = "FocusStates")]
44 [TemplatePartAttribute (Name = "ContentElement", Type = typeof (FrameworkElement))]
45 [TemplatePartAttribute (Name = "DisabledVisualElement", Type = typeof (FrameworkElement))]
46 [TemplatePartAttribute (Name = "FocusVisualElement", Type = typeof (FrameworkElement))]
47 [TemplatePartAttribute (Name = "ReadOnlyVisualElement", Type = typeof (FrameworkElement))]
48 [TemplatePartAttribute (Name = "RootElement", Type = typeof (FrameworkElement))]
49 public partial class TextBox : Control {
50 object contentElement;
52 bool IsFocused {
53 get; set;
56 bool IsMouseOver {
57 get; set;
60 static TextBox ()
62 IsReadOnlyProperty.AddPropertyChangeCallback (IsReadOnlyChanged);
63 TextProperty.AddPropertyChangeCallback (TextPropertyChanged);
66 void Initialize ()
68 // FIXME: Should use Events.AddOnEventHandler or something similar.
69 CursorPositionChanged += OnCursorPositionChanged;
72 static void IsReadOnlyChanged (DependencyObject sender, DependencyPropertyChangedEventArgs args)
74 TextBox textbox = sender as TextBox;
75 textbox.ChangeVisualState (false);
77 if (textbox.AutomationPeer != null)
78 textbox.AutomationPeer.RaisePropertyChangedEvent (ValuePatternIdentifiers.IsReadOnlyProperty,
79 args.OldValue,
80 args.NewValue);
83 static void TextPropertyChanged (DependencyObject sender, DependencyPropertyChangedEventArgs args)
85 ((TextBox) sender).RaiseUIATextChanged (args);
88 internal override void InvokeIsEnabledPropertyChanged ()
90 base.InvokeIsEnabledPropertyChanged ();
91 ChangeVisualState (false);
94 internal override void InvokeOnApplyTemplate ()
96 base.InvokeOnApplyTemplate ();
97 ChangeVisualState (false);
100 protected override void OnKeyDown (KeyEventArgs k)
102 // Chain up to our parent first, so that TabNavigation
103 // works as well as allowing developers to filter our
104 // input.
105 base.OnKeyDown (k);
107 if (!k.Handled)
108 NativeMethods.text_box_base_on_key_down (native, k.NativeHandle);
111 internal override void PostOnKeyDown (KeyEventArgs k)
113 base.PostOnKeyDown (k);
115 if (!k.Handled)
116 NativeMethods.text_box_base_post_on_key_down (native, k.NativeHandle);
119 protected override void OnKeyUp (KeyEventArgs k)
121 base.OnKeyUp (k);
123 if (!k.Handled)
124 NativeMethods.text_box_base_on_key_up (native, k.NativeHandle);
127 protected override void OnMouseLeftButtonDown (MouseButtonEventArgs e)
129 if (!e.Handled)
130 NativeMethods.text_box_base_on_mouse_left_button_down (native, e.NativeHandle);
132 base.OnMouseLeftButtonDown (e);
135 protected override void OnMouseLeftButtonUp (MouseButtonEventArgs e)
137 if (!e.Handled)
138 NativeMethods.text_box_base_on_mouse_left_button_up (native, e.NativeHandle);
140 base.OnMouseLeftButtonUp (e);
143 protected override void OnMouseMove (MouseEventArgs e)
145 NativeMethods.text_box_base_on_mouse_move (native, e.NativeHandle);
146 base.OnMouseMove (e);
149 protected override void OnMouseEnter (MouseEventArgs e)
151 IsMouseOver = true;
152 ChangeVisualState ();
153 base.OnMouseEnter (e);
156 protected override void OnMouseLeave (MouseEventArgs e)
158 IsMouseOver = false;
159 ChangeVisualState ();
160 base.OnMouseLeave (e);
163 protected override void OnGotFocus (RoutedEventArgs e)
165 IsFocused = true;
166 ChangeVisualState ();
167 base.OnGotFocus (e);
168 NativeMethods.text_box_base_on_got_focus (native, e.NativeHandle);
171 protected override void OnLostFocus (RoutedEventArgs e)
173 IsFocused = false;
174 ChangeVisualState ();
175 base.OnLostFocus (e);
176 NativeMethods.text_box_base_on_lost_focus (native, e.NativeHandle);
179 protected override Size ArrangeOverride (Size finalSize)
181 return base.ArrangeOverride (finalSize);
184 public string Text {
185 get {
186 return (string)GetValue (TextProperty) ?? "";
188 set {
189 if (value == null)
190 throw new ArgumentNullException ("Text cannot be null");
191 SetValue (TextProperty, value);
195 public void Select (int start, int length)
197 if (start < 0)
198 throw new ArgumentOutOfRangeException ("start");
200 if (length < 0)
201 throw new ArgumentOutOfRangeException ("length");
203 NativeMethods.text_box_base_select (this.native, start, length);
206 public void SelectAll ()
208 NativeMethods.text_box_base_select_all (native);
211 void OnCursorPositionChanged (object sender, CursorPositionChangedEventArgs args)
213 if (contentElement == null)
214 contentElement = GetTemplateChild ("ContentElement");
216 if (contentElement != null && contentElement is ScrollViewer) {
217 ScrollViewer scrollview = contentElement as ScrollViewer;
218 double offset = scrollview.HorizontalOffset;
220 // Note: for horizontal scrollage, we offset by 1.0 pixel for the width of the cursor ibeam
222 if (args.CursorX < offset) {
223 // need to scroll to the left a bit
224 scrollview.ScrollToHorizontalOffset (Math.Max (args.CursorX - 1.0, 0.0));
225 } else if (args.CursorX > offset + scrollview.ViewportWidth) {
226 // need to scroll to the right
227 offset = (args.CursorX + 1.0) - scrollview.ViewportWidth;
228 scrollview.ScrollToHorizontalOffset (offset);
231 offset = scrollview.VerticalOffset;
232 if (args.CursorY < offset) {
233 // need to scroll up a bit
234 scrollview.ScrollToVerticalOffset (args.CursorY);
235 } else if (args.CursorY + args.CursorHeight > offset + scrollview.ViewportHeight) {
236 // need to scroll down a bit
237 offset = (args.CursorY + args.CursorHeight) - Math.Max (args.CursorHeight, scrollview.ViewportHeight);
238 scrollview.ScrollToVerticalOffset (offset);
243 event CursorPositionChangedEventHandler CursorPositionChanged {
244 add {
245 RegisterEvent (EventIds.TextBoxBase_CursorPositionChangedEvent, value,
246 Events.CreateCursorPositionChangedEventHandlerDispatcher (value));
248 remove {
249 UnregisterEvent (EventIds.TextBoxBase_CursorPositionChangedEvent, value);
253 void ChangeVisualState ()
255 ChangeVisualState (true);
258 void ChangeVisualState (bool useTransitions)
260 if (!IsEnabled) {
261 VisualStateManager.GoToState (this, "Disabled", useTransitions);
262 } else if (IsReadOnly) {
263 VisualStateManager.GoToState (this, "ReadOnly", useTransitions);
264 } else if (IsMouseOver) {
265 VisualStateManager.GoToState (this, "MouseOver", useTransitions);
266 } else {
267 VisualStateManager.GoToState (this, "Normal", useTransitions);
270 if (IsFocused) {
271 VisualStateManager.GoToState (this, "Focused", useTransitions);
272 } else {
273 VisualStateManager.GoToState (this, "Unfocused", useTransitions);
277 protected override AutomationPeer OnCreateAutomationPeer ()
279 return new TextBoxAutomationPeer (this);
282 #region UIA Events
284 internal event DependencyPropertyChangedEventHandler UIATextChanged;
286 internal void RaiseUIATextChanged (DependencyPropertyChangedEventArgs args)
288 if (UIATextChanged != null)
289 UIATextChanged (this, args);
292 #endregion