1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
20 #include "namescope.h"
21 #include "application.h"
23 #include "tabnavigationwalker.h"
27 SetObjectType (Type::CONTROL
);
29 applied_template
= NULL
;
31 enabled_parent
= true;
42 if (applied_template
) {
43 applied_template
->unref();
44 applied_template
= NULL
;
48 template_root
->unref ();
52 FrameworkElement::Dispose ();
56 Control::FindElementsInHostCoordinates (cairo_t
*cr
, Point p
, List
*uielement_list
)
59 FrameworkElement::FindElementsInHostCoordinates (cr
, p
, uielement_list
);
63 Control::HitTest (cairo_t
*cr
, Point p
, List
*uielement_list
)
66 FrameworkElement::HitTest (cr
, p
, uielement_list
);
70 Control::InsideObject (cairo_t
*cr
, double x
, double y
)
73 * Controls don't get hit themselves the rendered elements
74 * do and it bubbles up
82 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
83 UIElement
*e
= GetVisualParent ();
84 while (e
&& !types
->IsSubclassOf (e
->GetObjectType (), Type::CONTROL
))
85 e
= e
->GetVisualParent ();
87 ((Control
*)e
)->UpdateEnabled ();
89 FrameworkElement::OnLoaded ();
93 Control::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
95 if (args
->GetProperty ()->GetOwnerType() != Type::CONTROL
) {
96 FrameworkElement::OnPropertyChanged (args
, error
);
100 if (args
->GetId () == Control::TemplateProperty
) {
103 InvalidateMeasure ();
105 else if (args
->GetId () == Control::PaddingProperty
106 || args
->GetId () == Control::BorderThicknessProperty
) {
107 InvalidateMeasure ();
108 } else if (args
->GetId () == Control::IsEnabledProperty
) {
109 if (!args
->GetNewValue ()->AsBool ()) {
110 Surface
*surface
= Deployment::GetCurrent ()->GetSurface ();
111 if (surface
&& surface
->GetFocusedElement () == this) {
112 // Ensure this element loses focus, then try to focus the next suitable element
113 surface
->FocusElement (NULL
);
114 TabNavigationWalker::Focus (this, true);
116 ReleaseMouseCapture ();
118 Emit (IsEnabledChangedEvent
);
119 } else if (args
->GetId () == Control::HorizontalContentAlignmentProperty
120 || args
->GetId () == Control::VerticalContentAlignmentProperty
) {
121 InvalidateArrange ();
123 NotifyListenersOfPropertyChange (args
, error
);
127 Control::SetVisualParent (UIElement
*visual_parent
)
129 FrameworkElement::SetVisualParent (visual_parent
);
130 if (!UIElement::IsSubtreeLoaded (this))
133 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
134 if (!visual_parent
) {
135 enabled_parent
= true;
137 UIElement
*parent
= GetVisualParent ();
139 if (!types
->IsSubclassOf (parent
->GetObjectType (), Type::CONTROL
)) {
140 parent
= parent
->GetVisualParent ();
143 this->enabled_parent
= ((Control
*)parent
)->GetIsEnabled ();
148 SetValue (Control::IsEnabledProperty
, Value (enabled_local
));
152 Control::SetValueWithErrorImpl (DependencyProperty
*property
, Value
*value
, MoonError
*error
)
154 if (property
->GetId () == Control::IsEnabledProperty
) {
155 this->enabled_local
= value
->AsBool ();
156 if ((enabled_local
&& enabled_parent
) == GetIsEnabled ())
159 Value
v (enabled_local
&& (enabled_parent
));
161 // If we don't propagate the changes down the tree here, the EnabledChanged events
162 // from the subtree are raised in the wrong order
163 bool b
= FrameworkElement::SetValueWithErrorImpl (property
, &v
, error
);
168 return FrameworkElement::SetValueWithErrorImpl (property
, value
, error
);
172 Control::ApplyTemplate ()
174 return ApplyTemplate (GetTemplate ());
178 Control::ApplyTemplate (FrameworkTemplate
*t
)
180 if (applied_template
== t
)
188 applied_template
= t
;
189 applied_template
->ref();
191 return ApplyTemplateRoot ((UIElement
*) applied_template
->GetVisualTree(this));
195 Control::ApplyTemplateRoot (UIElement
*root
)
197 if (!root
|| root
== template_root
)
203 root
->SetParent (this, &e
);
210 Control::ClearTemplate ()
212 if (applied_template
) {
213 applied_template
->unref();
214 applied_template
= NULL
;
217 ElementRemoved (template_root
);
221 Control::OnApplyTemplate ()
223 Emit (TemplateAppliedEvent
);
227 Control::ElementAdded (UIElement
*item
)
229 if (item
== template_root
)
232 ElementRemoved (template_root
);
234 template_root
= item
;
237 template_root
->ref ();
238 FrameworkElement::ElementAdded (template_root
);
241 SetSubtreeObject (template_root
);
245 Control::ElementRemoved (UIElement
*item
)
247 if (template_root
&& item
== template_root
) {
248 template_root
->unref ();
249 template_root
= NULL
;
250 SetSubtreeObject (NULL
);
254 FrameworkElement::ElementRemoved (item
);
258 Control::GetTemplateChild (const char *name
)
261 return template_root
->FindName (name
);
267 Control::Focus (bool recurse
)
269 Surface
*surface
= GetSurface ();
273 /* according to msdn, these three things must be true for an element to be focusable:
275 * 1. the element must be visible
276 * 2. the element must have IsTabStop = true
277 * 3. the element must be part of the plugin's visual tree, and must have had its Loaded event fired.
281 * If the current control is not focusable, we walk the visual tree and stop as soon
282 * as we find the first focusable child. That then becomes focused
284 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
285 DeepTreeWalker
walker (this);
286 while (UIElement
*e
= walker
.Step ()) {
287 if (!types
->IsSubclassOf (e
->GetObjectType (), Type::CONTROL
))
290 Control
*c
= (Control
*)e
;
291 if (!c
->GetIsEnabled ()) {
295 walker
.SkipBranch ();
299 // A control is focusable if it is attached to a visual tree whose root
300 // element has been loaded
302 for (UIElement
*check
= this; !loaded
&& check
!= NULL
; check
= check
->GetVisualParent ())
303 loaded
|= check
->IsLoaded ();
305 if (loaded
&& c
->GetRenderVisible () && c
->GetIsTabStop ())
306 return surface
->FocusElement (c
);
315 Control::UpdateEnabled ()
317 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
318 DeepTreeWalker walker
= DeepTreeWalker (this);
319 while (UIElement
*child
= walker
.Step ()) {
320 if (child
== this || !types
->IsSubclassOf (child
->GetObjectType (), Type::CONTROL
))
323 Control
*control
= (Control
*)child
;
324 control
->enabled_parent
= (enabled_local
&& enabled_parent
);
325 control
->SetValue (Control::IsEnabledProperty
, Value (control
->enabled_local
));
326 walker
.SkipBranch ();