3 // Moonlight List (moonlight-list@lists.ximian.com)
5 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
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.
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
;
62 IsReadOnlyProperty
.AddPropertyChangeCallback (IsReadOnlyChanged
);
63 TextProperty
.AddPropertyChangeCallback (TextPropertyChanged
);
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
,
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
108 NativeMethods
.text_box_base_on_key_down (native
, k
.NativeHandle
);
111 internal override void PostOnKeyDown (KeyEventArgs k
)
113 base.PostOnKeyDown (k
);
116 NativeMethods
.text_box_base_post_on_key_down (native
, k
.NativeHandle
);
119 protected override void OnKeyUp (KeyEventArgs k
)
124 NativeMethods
.text_box_base_on_key_up (native
, k
.NativeHandle
);
127 protected override void OnMouseLeftButtonDown (MouseButtonEventArgs e
)
130 NativeMethods
.text_box_base_on_mouse_left_button_down (native
, e
.NativeHandle
);
132 base.OnMouseLeftButtonDown (e
);
135 protected override void OnMouseLeftButtonUp (MouseButtonEventArgs e
)
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
)
152 ChangeVisualState ();
153 base.OnMouseEnter (e
);
156 protected override void OnMouseLeave (MouseEventArgs e
)
159 ChangeVisualState ();
160 base.OnMouseLeave (e
);
163 protected override void OnGotFocus (RoutedEventArgs e
)
166 ChangeVisualState ();
168 NativeMethods
.text_box_base_on_got_focus (native
, e
.NativeHandle
);
171 protected override void OnLostFocus (RoutedEventArgs e
)
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
);
186 return (string)GetValue (TextProperty
) ?? "";
190 throw new ArgumentNullException ("Text cannot be null");
191 SetValue (TextProperty
, value);
195 public void Select (int start
, int length
)
198 throw new ArgumentOutOfRangeException ("start");
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
{
245 RegisterEvent (EventIds
.TextBoxBase_CursorPositionChangedEvent
, value,
246 Events
.CreateCursorPositionChangedEventHandlerDispatcher (value));
249 UnregisterEvent (EventIds
.TextBoxBase_CursorPositionChangedEvent
, value);
253 void ChangeVisualState ()
255 ChangeVisualState (true);
258 void ChangeVisualState (bool useTransitions
)
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
);
267 VisualStateManager
.GoToState (this, "Normal", useTransitions
);
271 VisualStateManager
.GoToState (this, "Focused", useTransitions
);
273 VisualStateManager
.GoToState (this, "Unfocused", useTransitions
);
277 protected override AutomationPeer
OnCreateAutomationPeer ()
279 return new TextBoxAutomationPeer (this);
284 internal event DependencyPropertyChangedEventHandler UIATextChanged
;
286 internal void RaiseUIATextChanged (DependencyPropertyChangedEventArgs args
)
288 if (UIATextChanged
!= null)
289 UIATextChanged (this, args
);