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) 2008 Novell, Inc. (http://www.novell.com)
23 // Moonlight Team (moonlight-list@lists.ximian.com)
27 using System
.Collections
.Generic
;
29 using System
.Windows
.Automation
;
30 using System
.Windows
.Controls
;
31 using System
.Windows
.Markup
;
32 using System
.Windows
.Media
;
35 namespace System
.Windows
.Automation
.Peers
{
37 public class FrameworkElementAutomationPeer
: AutomationPeer
{
39 private FrameworkElement owner
;
41 public FrameworkElementAutomationPeer (FrameworkElement owner
)
44 throw new NullReferenceException ("owner");
47 // Default Automation events
48 owner
.GotFocus
+= (o
, a
) => {
49 RaisePropertyChangedEvent (AutomationElementIdentifiers
.HasKeyboardFocusProperty
,
53 owner
.LostFocus
+= (o
, a
) => {
54 RaisePropertyChangedEvent (AutomationElementIdentifiers
.HasKeyboardFocusProperty
,
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
;
68 control
.IsEnabledChanged
+= (o
, e
) => {
69 RaisePropertyChangedEvent (AutomationElementIdentifiers
.IsEnabledProperty
,
75 public UIElement 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
);
98 protected override List
<AutomationPeer
> GetChildrenCore ()
103 public override object GetPattern (PatternInterface pattern
)
108 public static AutomationPeer
FromElement (UIElement element
)
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 ()
187 protected override bool IsControlElementCore ()
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
202 protected override bool IsKeyboardFocusableCore ()
207 protected override bool IsOffscreenCore ()
212 protected override bool IsPasswordCore ()
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
)
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.
257 FrameworkElement parent
= VisualTreeHelper
.GetParent (element
) as FrameworkElement
;
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
);
267 return GetParentPeer (parent
);
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
{
283 internal virtual string ClassNameCore
{
287 internal virtual List
<AutomationPeer
> ChildrenCore
{
288 get { return GetChildrenRecursively (owner); }
291 internal virtual bool PasswordCore
{
292 get { return false; }
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
;
310 = FrameworkElementAutomationPeer
.CreatePeerForElement (element
);
314 List
<AutomationPeer
> returnedChildren
315 = GetChildrenRecursively (element
);
316 if (returnedChildren
!= null)
317 children
.AddRange (returnedChildren
);
321 if (children
.Count
== 0)
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);
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
) { }
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
))
351 if (double.IsNaN (height
))
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.
358 height
= (double) owner
.GetValue (FrameworkElement
.ActualHeightProperty
);
360 width
= (double) owner
.GetValue (FrameworkElement
.ActualWidthProperty
);
362 return new Rect (location
.X
, location
.Y
, width
, height
);