2009-09-29 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / class / System.Windows / System.Windows.Automation.Peers / FrameworkElementAutomationPeer.cs
blob90df295b976c72e7cfaad0e8ecf96954a6af739f
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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) 2008 Novell, Inc. (http://www.novell.com)
22 // Contact:
23 // Moonlight Team (moonlight-list@lists.ximian.com)
26 using System;
27 using System.Collections.Generic;
28 using System.Windows;
29 using System.Windows.Automation;
30 using System.Windows.Controls;
31 using System.Windows.Markup;
32 using System.Windows.Media;
33 using System.Linq;
35 namespace System.Windows.Automation.Peers {
37 public class FrameworkElementAutomationPeer : AutomationPeer {
39 private FrameworkElement owner;
41 public FrameworkElementAutomationPeer (FrameworkElement owner)
43 if (owner == null)
44 throw new NullReferenceException ("owner");
45 this.owner = owner;
47 // Default Automation events
48 owner.GotFocus += (o, a) => {
49 RaisePropertyChangedEvent (AutomationElementIdentifiers.HasKeyboardFocusProperty,
50 false,
51 true);
53 owner.LostFocus += (o, a) => {
54 RaisePropertyChangedEvent (AutomationElementIdentifiers.HasKeyboardFocusProperty,
55 true,
56 false);
59 owner.SizeChanged += (o, s) => {
60 Point location = GetLocation (owner);
61 RaisePropertyChangedEvent (AutomationElementIdentifiers.BoundingRectangleProperty,
62 new Rect (0, 0, s.PreviousSize.Width, s.PreviousSize.Height),
63 new Rect (location.X, location.Y, s.NewSize.Width, s.NewSize.Height));
66 Control control = owner as Control;
67 if (control != null)
68 control.IsEnabledChanged += (o, e) => {
69 RaisePropertyChangedEvent (AutomationElementIdentifiers.IsEnabledProperty,
70 e.OldValue,
71 e.NewValue);
75 public UIElement Owner {
76 get { return owner; }
79 protected override string GetNameCore ()
81 return owner.GetValue (AutomationProperties.NameProperty) as string ?? string.Empty;
84 protected override string GetItemTypeCore ()
86 return owner.GetValue (AutomationProperties.ItemTypeProperty) as string ?? string.Empty;
89 protected override AutomationPeer GetLabeledByCore ()
91 UIElement labeledBy = owner.GetValue (AutomationProperties.LabeledByProperty) as UIElement;
92 if (labeledBy != null)
93 return FrameworkElementAutomationPeer.CreatePeerForElement (labeledBy);
94 else
95 return null;
98 protected override List<AutomationPeer> GetChildrenCore ()
100 return ChildrenCore;
103 public override object GetPattern (PatternInterface pattern)
105 return null;
108 public static AutomationPeer FromElement (UIElement element)
110 if (element == null)
111 throw new ArgumentNullException ("element");
112 return element.AutomationPeer;
115 protected override string GetAcceleratorKeyCore ()
117 return owner.GetValue (AutomationProperties.AcceleratorKeyProperty) as string ?? string.Empty;
120 protected override string GetAccessKeyCore ()
122 return owner.GetValue (AutomationProperties.AccessKeyProperty) as string ?? string.Empty;
125 protected override AutomationControlType GetAutomationControlTypeCore ()
127 // Some Peers don't override GetAutomationControlTypeCore and return something different to Custom
128 // for example: TextBoxAutomationPeer
129 return AutomationControlTypeCore.HasValue ? AutomationControlTypeCore.Value : AutomationControlType.Custom;
132 protected override string GetAutomationIdCore ()
134 return owner.GetValue (AutomationProperties.AutomationIdProperty) as string ?? string.Empty;
137 protected override Rect GetBoundingRectangleCore ()
139 if (VisualTreeHelper.GetParent (owner) == null)
140 return new Rect (0, 0, 0, 0);
142 return GetBoundingRectangleFrom (owner);
145 protected override string GetClassNameCore ()
147 return ClassNameCore ?? string.Empty;
150 protected override Point GetClickablePointCore ()
152 return new Point (0, 0);
155 protected override string GetHelpTextCore ()
157 return owner.GetValue (AutomationProperties.HelpTextProperty) as string ?? string.Empty;
160 protected override string GetItemStatusCore ()
162 return owner.GetValue (AutomationProperties.ItemStatusProperty) as string ?? string.Empty;
165 protected override string GetLocalizedControlTypeCore ()
167 // LAMESPEC: http://msdn.microsoft.com/en-us/library/ms743581.aspx
168 // "CamelCase" literal values should be "camel case", not "camelcase"
169 return GetAutomationControlType ().ToString ().ToLower ();
172 protected override AutomationOrientation GetOrientationCore ()
174 return AutomationOrientation.None;
177 protected override bool HasKeyboardFocusCore ()
179 return owner == System.Windows.Input.FocusManager.GetFocusedElement ();
182 protected override bool IsContentElementCore ()
184 return true;
187 protected override bool IsControlElementCore ()
189 return true;
192 protected override bool IsEnabledCore ()
194 Control ownerAsControl = owner as Control;
195 if (ownerAsControl != null)
196 return ownerAsControl.IsEnabled;
198 // Fall back to default value
199 return true;
202 protected override bool IsKeyboardFocusableCore ()
204 return false;
207 protected override bool IsOffscreenCore ()
209 return false;
212 protected override bool IsPasswordCore ()
214 return PasswordCore;
217 protected override bool IsRequiredForFormCore ()
219 bool? isRequired = (bool?) owner.GetValue (AutomationProperties.IsRequiredForFormProperty);
220 return isRequired.HasValue ? isRequired.Value : false;
223 protected override void SetFocusCore ()
225 Control ownerAsControl = owner as Control;
226 if (ownerAsControl != null)
227 ownerAsControl.Focus ();
230 public static AutomationPeer CreatePeerForElement (UIElement element)
232 if (element == null)
233 throw new ArgumentNullException ("element");
234 if (element.AutomationPeer == null) {
235 element.AutomationPeer = element.CreateAutomationPeer ();
236 // We need to cache old values to raise PropertyChanged events
237 // when calling AutomationPeer.InvalidatePeer()
238 if (element.AutomationPeer != null)
239 element.AutomationPeer.CacheMainProperties ();
241 return element.AutomationPeer;
244 internal override AutomationPeer GetParentCore ()
246 return GetParentPeer (owner);
249 #region Private Methods
251 private AutomationPeer GetParentPeer (FrameworkElement element)
253 // We are returning parents of children already instantiated.
254 if (element == null)
255 return null;
257 FrameworkElement parent = VisualTreeHelper.GetParent (element) as FrameworkElement;
258 if (parent == null)
259 return null;
261 // Some parents don't return an Automation Peer (for example: Border or Panel subclasses)
262 // We need to create the Peer because some Peers return children that don't
263 // necesarily return this peer when calling GetParent
264 // (for example: ListBox when Template is not null)
265 AutomationPeer peer = FrameworkElementAutomationPeer.CreatePeerForElement (parent);
266 if (peer == null)
267 return GetParentPeer (parent);
268 else
269 return peer;
272 #endregion
274 #region Internal properties
276 // Internal properties used by Peers that don't override XXXXCore and return something else
277 // than FrameworkElementAutomationPeer's default value.
279 internal virtual AutomationControlType? AutomationControlTypeCore {
280 get { return null; }
283 internal virtual string ClassNameCore {
284 get { return null; }
287 internal virtual List<AutomationPeer> ChildrenCore {
288 get { return GetChildrenRecursively (owner); }
291 internal virtual bool PasswordCore {
292 get { return false; }
295 #endregion
297 #region Internal methods
299 internal static List<AutomationPeer> GetChildrenRecursively (UIElement uielement)
301 List<AutomationPeer> children = new List<AutomationPeer> ();
302 int childrenCount = VisualTreeHelper.GetChildrenCount (uielement);
304 for (int child = 0; child < childrenCount; child++) {
305 UIElement element = VisualTreeHelper.GetChild (uielement, child) as UIElement;
306 if (element == null)
307 continue;
309 AutomationPeer peer
310 = FrameworkElementAutomationPeer.CreatePeerForElement (element);
311 if (peer != null)
312 children.Add (peer);
313 else {
314 List<AutomationPeer> returnedChildren
315 = GetChildrenRecursively (element);
316 if (returnedChildren != null)
317 children.AddRange (returnedChildren);
321 if (children.Count == 0)
322 return null;
324 return children;
327 internal Point GetLocation (FrameworkElement owner)
329 if (VisualTreeHelper.GetParent (owner) == null)
330 return new Point (0, 0);
332 Point point = new Point (0, 0);
333 try {
334 // This happens when an item is not visible yet but exists, for
335 // example ListBoxItems in ComboBox when Template is not null
336 point = owner.TransformToVisual (Application.Current.RootVisual).Transform (new Point ());
337 } catch (ArgumentException) { }
339 return point;
342 internal Rect GetBoundingRectangleFrom (FrameworkElement owner)
344 Point location = GetLocation (owner);
346 double width = (double) owner.GetValue (FrameworkElement.WidthProperty);
347 double height = (double) owner.GetValue (FrameworkElement.HeightProperty);
349 if (double.IsNaN (width))
350 width = 0;
351 if (double.IsNaN (height))
352 height = 0;
354 // Some Controls may not be honoring the specified Height or Width and would
355 // use a different value, that's why we need to test these properties too,
356 // Examples of those Controls are TextBlock and Image.
357 if (height == 0)
358 height = (double) owner.GetValue (FrameworkElement.ActualHeightProperty);
359 if (width == 0)
360 width = (double) owner.GetValue (FrameworkElement.ActualWidthProperty);
362 return new Rect (location.X, location.Y, width, height);
365 #endregion