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
.Peers
;
30 using System
.Windows
.Input
;
31 using System
.Windows
.Media
;
32 using System
.Windows
.Documents
;
33 using System
.Collections
.Generic
;
35 namespace System
.Windows
.Controls
{
37 [TemplateVisualStateAttribute (Name
= "Disabled", GroupName
= "CommonStates")]
38 [TemplateVisualStateAttribute (Name
= "Normal", GroupName
= "CommonStates")]
39 [TemplateVisualStateAttribute (Name
= "MouseOver", GroupName
= "CommonStates")]
40 [TemplateVisualStateAttribute (Name
= "ReadOnly", GroupName
= "CommonStates")]
41 [TemplateVisualStateAttribute (Name
= "Focused", GroupName
= "FocusStates")]
42 [TemplateVisualStateAttribute (Name
= "Unfocused", GroupName
= "FocusStates")]
43 [TemplatePartAttribute (Name
= "ContentElement", Type
= typeof (FrameworkElement
))]
44 [TemplatePartAttribute (Name
= "DisabledVisualElement", Type
= typeof (FrameworkElement
))]
45 [TemplatePartAttribute (Name
= "FocusVisualElement", Type
= typeof (FrameworkElement
))]
46 [TemplatePartAttribute (Name
= "ReadOnlyVisualElement", Type
= typeof (FrameworkElement
))]
47 [TemplatePartAttribute (Name
= "RootElement", Type
= typeof (FrameworkElement
))]
48 public partial class TextBox
: Control
{
49 object contentElement
;
59 internal override void Initialize ()
63 CursorPositionChanged
+= OnCursorPositionChanged
;
64 IsEnabledChanged
+= delegate { ChangeVisualState (); }
;
65 Loaded
+= delegate { ChangeVisualState (); }
;
68 internal override void InvokeKeyDown (KeyEventArgs k
)
70 base.InvokeKeyDown (k
);
73 NativeMethods
.text_box_base_on_character_key_down (native
, k
.NativeHandle
);
76 protected override void OnKeyDown (KeyEventArgs k
)
78 // Chain up to our parent first, so that TabNavigation
79 // works as well as allowing developers to filter our
84 NativeMethods
.text_box_base_on_key_down (native
, k
.NativeHandle
);
87 protected override void OnKeyUp (KeyEventArgs k
)
92 NativeMethods
.text_box_base_on_key_up (native
, k
.NativeHandle
);
95 protected override void OnMouseLeftButtonDown (MouseButtonEventArgs e
)
98 NativeMethods
.text_box_base_on_mouse_left_button_down (native
, e
.NativeHandle
);
100 base.OnMouseLeftButtonDown (e
);
103 protected override void OnMouseLeftButtonUp (MouseButtonEventArgs e
)
106 NativeMethods
.text_box_base_on_mouse_left_button_up (native
, e
.NativeHandle
);
108 base.OnMouseLeftButtonUp (e
);
111 protected override void OnMouseMove (MouseEventArgs e
)
113 NativeMethods
.text_box_base_on_mouse_move (native
, e
.NativeHandle
);
114 base.OnMouseMove (e
);
117 protected override void OnMouseEnter (MouseEventArgs e
)
120 base.OnMouseEnter (e
);
121 ChangeVisualState ();
124 protected override void OnMouseLeave (MouseEventArgs e
)
127 base.OnMouseLeave (e
);
128 ChangeVisualState ();
131 protected override void OnGotFocus (RoutedEventArgs e
)
135 NativeMethods
.text_box_base_on_got_focus (native
, e
.NativeHandle
);
136 ChangeVisualState ();
139 protected override void OnLostFocus (RoutedEventArgs e
)
142 base.OnLostFocus (e
);
143 NativeMethods
.text_box_base_on_lost_focus (native
, e
.NativeHandle
);
144 ChangeVisualState ();
149 return (string)GetValue (TextProperty
) ?? "";
153 throw new ArgumentNullException ("Text cannot be null");
154 SetValue (TextProperty
, value);
158 public void Select (int start
, int length
)
161 throw new ArgumentOutOfRangeException ("start");
164 throw new ArgumentOutOfRangeException ("length");
166 NativeMethods
.text_box_base_select (this.native
, start
, length
);
169 public void SelectAll ()
171 NativeMethods
.text_box_base_select_all (native
);
174 static UnmanagedEventHandler cursor_position_changed
= Events
.CreateSafeHandler (cursor_position_changed_cb
);
175 static UnmanagedEventHandler selection_changed
= Events
.CreateSafeHandler (selection_changed_cb
);
176 static UnmanagedEventHandler text_changed
= Events
.CreateSafeHandler (text_changed_cb
);
178 static object CursorPositionChangedEvent
= new object ();
179 static object SelectionChangedEvent
= new object ();
180 static object TextChangedEvent
= new object ();
182 void OnCursorPositionChanged (object sender
, CursorPositionChangedEventArgs args
)
184 if (contentElement
== null)
185 contentElement
= GetTemplateChild ("ContentElement");
187 if (contentElement
!= null && contentElement
is ScrollViewer
) {
188 ScrollViewer scrollview
= contentElement
as ScrollViewer
;
189 double offset
= scrollview
.HorizontalOffset
;
191 // Note: for horizontal scrollage, we offset by 1.0 pixel for the width of the cursor ibeam
193 if (args
.CursorX
< offset
) {
194 // need to scroll to the left a bit
195 scrollview
.ScrollToHorizontalOffset (Math
.Max (args
.CursorX
- 1.0, 0.0));
196 } else if (args
.CursorX
> offset
+ scrollview
.ViewportWidth
) {
197 // need to scroll to the right
198 offset
= (args
.CursorX
+ 1.0) - scrollview
.ViewportWidth
;
199 scrollview
.ScrollToHorizontalOffset (offset
);
202 offset
= scrollview
.VerticalOffset
;
203 if (args
.CursorY
< offset
) {
204 // need to scroll up a bit
205 scrollview
.ScrollToVerticalOffset (args
.CursorY
);
206 } else if (args
.CursorY
+ args
.CursorHeight
> offset
+ scrollview
.ViewportHeight
) {
207 // need to scroll down a bit
208 offset
= (args
.CursorY
+ args
.CursorHeight
) - Math
.Max (args
.CursorHeight
, scrollview
.ViewportHeight
);
209 scrollview
.ScrollToVerticalOffset (offset
);
214 void InvokeCursorPositionChanged (CursorPositionChangedEventArgs args
)
216 CursorPositionChangedEventHandler h
= (CursorPositionChangedEventHandler
) EventList
[CursorPositionChangedEvent
];
222 static void cursor_position_changed_cb (IntPtr target
, IntPtr calldata
, IntPtr closure
)
224 TextBox textbox
= (TextBox
) NativeDependencyObjectHelper
.FromIntPtr (closure
);
225 CursorPositionChangedEventArgs args
= new CursorPositionChangedEventArgs (calldata
);
227 textbox
.InvokeCursorPositionChanged (args
);
230 event CursorPositionChangedEventHandler CursorPositionChanged
{
232 RegisterEvent (CursorPositionChangedEvent
, "CursorPositionChanged", cursor_position_changed
, value);
235 UnregisterEvent (CursorPositionChangedEvent
, "CursorPositionChanged", cursor_position_changed
, value);
239 void InvokeSelectionChanged (RoutedEventArgs args
)
241 RoutedEventHandler h
= (RoutedEventHandler
) EventList
[SelectionChangedEvent
];
247 static void selection_changed_cb (IntPtr target
, IntPtr calldata
, IntPtr closure
)
249 TextBox textbox
= (TextBox
) NativeDependencyObjectHelper
.FromIntPtr (closure
);
250 RoutedEventArgs args
= new RoutedEventArgs (calldata
, false);
252 textbox
.InvokeSelectionChanged (args
);
255 public event RoutedEventHandler SelectionChanged
{
257 RegisterEvent (SelectionChangedEvent
, "SelectionChanged", selection_changed
, value);
260 UnregisterEvent (SelectionChangedEvent
, "SelectionChanged", selection_changed
, value);
264 void InvokeTextChanged (TextChangedEventArgs args
)
266 TextChangedEventHandler h
= (TextChangedEventHandler
) EventList
[TextChangedEvent
];
272 static void text_changed_cb (IntPtr target
, IntPtr calldata
, IntPtr closure
)
274 TextBox textbox
= (TextBox
) NativeDependencyObjectHelper
.FromIntPtr (closure
);
275 TextChangedEventArgs args
= new TextChangedEventArgs (calldata
);
277 textbox
.InvokeTextChanged (args
);
280 public event TextChangedEventHandler TextChanged
{
282 RegisterEvent (TextChangedEvent
, "TextChanged", text_changed
, value);
285 UnregisterEvent (TextChangedEvent
, "TextChanged", text_changed
, value);
289 void ChangeVisualState ()
291 ChangeVisualState (true);
294 void ChangeVisualState (bool useTransitions
)
297 VisualStateManager
.GoToState (this, "Disabled", useTransitions
);
298 } else if (IsReadOnly
) {
299 VisualStateManager
.GoToState (this, "ReadOnly", useTransitions
);
300 } else if (IsMouseOver
) {
301 VisualStateManager
.GoToState (this, "MouseOver", useTransitions
);
303 VisualStateManager
.GoToState (this, "Normal", useTransitions
);
307 VisualStateManager
.GoToState (this, "Focused", useTransitions
);
309 VisualStateManager
.GoToState (this, "Unfocused", useTransitions
);
313 protected override AutomationPeer
OnCreateAutomationPeer ()
315 return new TextBoxAutomationPeer (this);