1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * frameworkelement.cpp:
5 * Copyright 2007 Novell, Inc. (http://www.novell.com)
7 * See the LICENSE file included with the distribution for details.
17 #include "application.h"
18 #include "deployment.h"
20 #include "namescope.h"
21 #include "frameworkelement.h"
23 #include "thickness.h"
24 #include "collection.h"
26 #include "validators.h"
28 #define MAX_LAYOUT_PASSES 250
30 FrameworkElementProvider::FrameworkElementProvider (DependencyObject
*obj
, PropertyPrecedence precedence
) : PropertyValueProvider (obj
, precedence
)
32 actual_height_value
= NULL
;
33 actual_width_value
= NULL
;
34 last
= Size (-INFINITY
, -INFINITY
);
37 FrameworkElementProvider::~FrameworkElementProvider ()
39 delete actual_height_value
;
40 delete actual_width_value
;
44 FrameworkElementProvider::GetPropertyValue (DependencyProperty
*property
)
46 if (property
->GetId () != FrameworkElement::ActualHeightProperty
&&
47 property
->GetId () != FrameworkElement::ActualWidthProperty
)
50 FrameworkElement
*element
= (FrameworkElement
*) obj
;
52 Size actual
= last
.IsEmpty () ? Size () : last
;
53 Surface
*surface
= obj
->GetSurface ();
55 if (!LayoutInformation::GetPreviousConstraint (obj
) || (surface
&& surface
->IsTopLevel (element
) && obj
->Is (Type::PANEL
)))
56 actual
= element
->ComputeActualSize ();
61 if (actual_height_value
)
62 delete actual_height_value
;
64 if (actual_width_value
)
65 delete actual_width_value
;
67 actual_height_value
= new Value (actual
.height
);
68 actual_width_value
= new Value (actual
.width
);
71 if (property
->GetId () == FrameworkElement::ActualHeightProperty
) {
72 return actual_height_value
;
74 return actual_width_value
;
78 FrameworkElement::FrameworkElement ()
80 SetObjectType (Type::FRAMEWORKELEMENT
);
82 default_style_applied
= false;
83 get_default_template_cb
= NULL
;
87 bounds_with_children
= Rect ();
88 logical_parent
= NULL
;
90 providers
[PropertyPrecedence_LocalStyle
] = new StylePropertyValueProvider (this, PropertyPrecedence_LocalStyle
);
91 providers
[PropertyPrecedence_DefaultStyle
] = new StylePropertyValueProvider (this, PropertyPrecedence_DefaultStyle
);
92 providers
[PropertyPrecedence_DynamicValue
] = new FrameworkElementProvider (this, PropertyPrecedence_DynamicValue
);
95 FrameworkElement::~FrameworkElement ()
100 FrameworkElement::RenderLayoutClip (cairo_t
*cr
)
102 Geometry
*geom
= LayoutInformation::GetClip (this);
114 FrameworkElement::GetTransformOrigin ()
116 Point
*user_xform_origin
= GetRenderTransformOrigin ();
118 double width
= GetActualWidth ();
119 double height
= GetActualHeight ();
121 return Point (width
* user_xform_origin
->x
,
122 height
* user_xform_origin
->y
);
126 FrameworkElement::SetLogicalParent (DependencyObject
*logical_parent
, MoonError
*error
)
128 if (logical_parent
&& this->logical_parent
&& this->logical_parent
!= logical_parent
) {
129 MoonError::FillIn (error
, MoonError::INVALID_OPERATION
, "Element is a child of another element");
133 this->logical_parent
= logical_parent
;
137 FrameworkElement::ElementAdded (UIElement
*item
)
139 UIElement::ElementAdded (item
);
141 //item->UpdateLayout ();
143 if (IsLayoutContainer () && item->Is (Type::FRAMEWORKELEMENT)) {
144 FrameworkElement *fe = (FrameworkElement *)item;
145 fe->SetActualWidth (0.0);
146 fe->SetActualHeight (0.0);
152 FrameworkElement::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
154 if (args
->GetProperty ()->GetOwnerType() != Type::FRAMEWORKELEMENT
) {
155 UIElement::OnPropertyChanged (args
, error
);
159 if (args
->GetId () == FrameworkElement::WidthProperty
||
160 args
->GetId () == FrameworkElement::MaxWidthProperty
||
161 args
->GetId () == FrameworkElement::MinWidthProperty
||
162 args
->GetId () == FrameworkElement::MaxHeightProperty
||
163 args
->GetId () == FrameworkElement::MinHeightProperty
||
164 args
->GetId () == FrameworkElement::HeightProperty
||
165 args
->GetId () == FrameworkElement::MarginProperty
) {
167 Point
*p
= GetRenderTransformOrigin ();
169 /* normally we'd only update the bounds of this
170 element on a width/height change, but if the render
171 transform is someplace other than (0,0), the
172 transform needs to be updated as well. */
173 FullInvalidate (p
->x
!= 0.0 || p
->y
!= 0.0);
175 FrameworkElement
*visual_parent
= (FrameworkElement
*)GetVisualParent ();
177 if (visual_parent
->Is (Type::CANVAS
)) {
178 if (!IsLayoutContainer ()) {
179 ClearValue (FrameworkElement::ActualHeightProperty
);
180 ClearValue (FrameworkElement::ActualWidthProperty
);
182 InvalidateMeasure ();
183 InvalidateArrange ();
185 visual_parent
->InvalidateMeasure ();
186 InvalidateMeasure ();
187 InvalidateArrange ();
190 InvalidateMeasure ();
191 InvalidateArrange ();
195 else if (args
->GetId () == FrameworkElement::StyleProperty
) {
196 if (args
->GetNewValue()) {
197 Style
*s
= args
->GetNewValue()->AsStyle ();
199 // this has a side effect of calling
200 // ProviderValueChanged on all values
201 // in the style, so we might end up
202 // with lots of property notifications
203 // here (reentrancy ok?)
205 Application::GetCurrent()->ApplyStyle (this, s
);
207 ((StylePropertyValueProvider
*)providers
[PropertyPrecedence_LocalStyle
])->SealStyle (s
);
211 else if (args
->GetId () == FrameworkElement::HorizontalAlignmentProperty
||
212 args
->GetId () == FrameworkElement::VerticalAlignmentProperty
) {
213 InvalidateArrange ();
214 FullInvalidate (true);
217 NotifyListenersOfPropertyChange (args
, error
);
221 FrameworkElement::ApplySizeConstraints (const Size
&size
)
223 Size
specified (GetWidth (), GetHeight ());
224 Size
constrained (GetMinWidth (), GetMinHeight ());
226 constrained
= constrained
.Max (size
);
228 if (!isnan (specified
.width
))
229 constrained
.width
= specified
.width
;
231 if (!isnan (specified
.height
))
232 constrained
.height
= specified
.height
;
234 constrained
= constrained
.Min (GetMaxWidth (), GetMaxHeight ());
235 constrained
= constrained
.Max (GetMinWidth (), GetMinHeight ());
241 FrameworkElement::ComputeBounds ()
243 Size
size (GetActualWidth (), GetActualHeight ());
244 size
= ApplySizeConstraints (size
);
246 extents
= Rect (0, 0, size
.width
, size
.height
);
248 bounds
= IntersectBoundsWithClipPath (extents
, false).Transform (&absolute_xform
);
249 bounds_with_children
= bounds
;
251 VisualTreeWalker walker
= VisualTreeWalker (this);
252 while (UIElement
*item
= walker
.Step ()) {
253 if (!item
->GetRenderVisible ())
256 bounds_with_children
= bounds_with_children
.Union (item
->GetSubtreeBounds ());
261 FrameworkElement::GetSubtreeBounds ()
263 VisualTreeWalker walker
= VisualTreeWalker (this);
264 if (GetSubtreeObject () != NULL
)
265 return bounds_with_children
;
271 FrameworkElement::ComputeActualSize ()
273 UIElement
*parent
= GetVisualParent ();
275 if ((parent
&& !parent
->Is (Type::CANVAS
)) || (!Is (Type::CANVAS
) && IsLayoutContainer ()))
276 return GetDesiredSize ();
280 actual
= ApplySizeConstraints (actual
);
286 FrameworkElement::InsideObject (cairo_t
*cr
, double x
, double y
)
288 double width
= GetActualWidth ();
289 double height
= GetActualHeight ();
290 double nx
= x
, ny
= y
;
292 TransformPoint (&nx
, &ny
);
293 if (nx
< 0 || ny
< 0 || nx
> width
|| ny
> height
)
296 Geometry
*layout_clip
= LayoutInformation::GetLayoutClip (this);
297 if (layout_clip
&& !layout_clip
->GetBounds ().PointInside (nx
, ny
))
300 return UIElement::InsideObject (cr
, x
, y
);
304 FrameworkElement::HitTest (cairo_t
*cr
, Point p
, List
*uielement_list
)
306 if (!GetRenderVisible ())
309 if (!GetHitTestVisible ())
312 // first a quick bounds check
313 if (!GetSubtreeBounds().PointInside (p
.x
, p
.y
))
316 if (!InsideClip (cr
, p
.x
, p
.y
))
319 /* create our node and stick it on front */
320 List::Node
*us
= uielement_list
->Prepend (new UIElementNode (this));
323 VisualTreeWalker walker
= VisualTreeWalker (this, ZReverse
);
324 while (UIElement
*child
= walker
.Step ()) {
325 child
->HitTest (cr
, p
, uielement_list
);
327 if (us
!= uielement_list
->First ()) {
333 if (!hit
&& !InsideObject (cr
, p
.x
, p
.y
))
334 uielement_list
->Remove (us
);
338 FrameworkElement::FindElementsInHostCoordinates (cairo_t
*cr
, Point host
, List
*uielement_list
)
340 if (!GetRenderVisible ())
343 if (!GetHitTestVisible ())
346 if (bounds_with_children
.height
<= 0)
353 RenderClipPath (cr
, true);
355 cairo_identity_matrix (cr
);
356 bool res
= cairo_in_fill (cr
, host
.x
, host
.y
);
364 /* create our node and stick it on front */
365 List::Node
*us
= uielement_list
->Prepend (new UIElementNode (this));
367 VisualTreeWalker walker
= VisualTreeWalker (this, ZForward
);
368 while (UIElement
*child
= walker
.Step ())
369 child
->FindElementsInHostCoordinates (cr
, host
, uielement_list
);
371 if (us
== uielement_list
->First ()) {
374 cairo_set_matrix (cr
, &absolute_xform
);
375 Render (cr
, &all
, true);
376 cairo_identity_matrix (cr
);
378 if (!CanFindElement () ||
379 !(cairo_in_fill (cr
, host
.x
, host
.y
) || cairo_in_stroke (cr
, host
.x
, host
.y
)))
380 uielement_list
->Remove (us
);
385 // FIXME: This is not the fastest way of implementing this, decomposing the rectangle into
386 // a series of points is probably going to be quite slow. It's a good first effort.
388 FrameworkElement::FindElementsInHostCoordinates (cairo_t
*cr
, Rect r
, List
*uielement_list
)
391 if (!GetRenderVisible ())
394 if (!GetHitTestVisible ())
397 if (bounds_with_children
.height
<= 0)
400 if (!bounds_with_children
.IntersectsWith (r
))
407 RenderClipPath (cr
, true);
409 cairo_identity_matrix (cr
);
411 for (int i
=r
.x
; i
< r
.x
+ r
.width
&& !res
; i
++)
412 for (int j
=r
.y
; j
< r
.y
+ r
.height
&& !res
; j
++)
413 res
= cairo_in_fill (cr
, i
, j
);
422 /* create our node and stick it on front */
423 List::Node
*us
= uielement_list
->Prepend (new UIElementNode (this));
425 VisualTreeWalker walker
= VisualTreeWalker (this, ZForward
);
426 while (UIElement
*child
= walker
.Step ())
427 child
->FindElementsInHostCoordinates (cr
, r
, uielement_list
);
429 if (us
== uielement_list
->First ()) {
432 cairo_set_matrix (cr
, &absolute_xform
);
433 Render (cr
, &all
, true);
434 cairo_identity_matrix (cr
);
437 if (CanFindElement ()) {
438 for (int i
= r
.x
; i
< (r
.x
+ r
.width
) && !res
; i
++)
439 for (int j
= r
.y
; j
< (r
.y
+ r
.height
) && !res
; j
++)
440 res
= cairo_in_fill (cr
, i
, j
) || cairo_in_stroke (cr
, i
, j
);
444 uielement_list
->Remove (us
);
450 FrameworkElement::GetSizeForBrush (cairo_t
*cr
, double *width
, double *height
)
452 *width
= GetActualWidth ();
453 *height
= GetActualHeight ();
457 FrameworkElement::Measure (Size availableSize
)
459 //LOG_LAYOUT ("measuring %p %s %g,%g\n", this, GetTypeName (), availableSize.width, availableSize.height);
462 if (!IsLayoutContainer ()) {
463 UIElement
*parent
= GetVisualParent ();
465 if (!parent
|| parent
->Is (Type::CANVAS
)) {
466 InvalidateArrange ();
468 dirty_flags
&= ~DirtyMeasure
;
473 Size
*last
= LayoutInformation::GetPreviousConstraint (this);
474 bool domeasure
= (this->dirty_flags
& DirtyMeasure
) > 0;
476 domeasure
|= !last
|| last
->width
!= availableSize
.width
|| last
->height
!= availableSize
.height
;
478 if (GetVisibility () == VisibilityCollapsed
) {
479 SetDesiredSize (Size (0,0));
486 LayoutInformation::SetPreviousConstraint (this, &availableSize
);
488 InvalidateArrange ();
491 dirty_flags
&= ~DirtyMeasure
;
493 Thickness margin
= *GetMargin ();
494 Size size
= availableSize
.GrowBy (-margin
);
496 size
= ApplySizeConstraints (size
);
499 size
= (*measure_cb
)(size
);
501 size
= MeasureOverride (size
);
503 // postcondition the results
504 size
= ApplySizeConstraints (size
);
506 size
= size
.GrowBy (margin
);
507 size
= size
.Min (availableSize
);
509 if (GetUseLayoutRounding ()) {
510 size
.width
= floor (size
.width
);
511 size
.height
= floor (size
.height
);
514 SetDesiredSize (size
);
518 FrameworkElement::MeasureOverride (Size availableSize
)
520 Size desired
= Size (0,0);
522 if (!IsLayoutContainer ())
525 availableSize
= ApplySizeConstraints (availableSize
);
527 VisualTreeWalker walker
= VisualTreeWalker (this);
528 while (UIElement
*child
= walker
.Step ()) {
529 if (child
->GetVisibility () != VisibilityVisible
)
532 child
->Measure (availableSize
);
533 desired
= child
->GetDesiredSize ();
536 desired
= ApplySizeConstraints (desired
);
542 // not sure about the disconnect between these two methods.. I would
543 // imagine both should take Rects and ArrangeOverride would return a
544 // rectangle as well..
546 FrameworkElement::Arrange (Rect finalRect
)
548 //LOG_LAYOUT ("arranging %p %s %g,%g,%g,%g\n", this, GetTypeName (), finalRect.x, finalRect.y, finalRect.width, finalRect.height);
549 Rect
*slot
= LayoutInformation::GetLayoutSlot (this);
550 bool doarrange
= this->dirty_flags
& DirtyArrange
;
552 doarrange
|= slot
? *slot
!= finalRect
: true;
554 if (finalRect
.width
< 0 || finalRect
.height
< 0
555 || isinf (finalRect
.width
) || isinf (finalRect
.height
)
556 || isnan (finalRect
.width
) || isnan (finalRect
.height
)) {
557 Size desired
= GetDesiredSize ();
558 g_warning ("invalid arguments to Arrange (%g,%g,%g,%g) Desired = (%g,%g)", finalRect
.x
, finalRect
.y
, finalRect
.width
, finalRect
.height
, desired
.width
, desired
.height
);
562 if (GetVisibility () == VisibilityCollapsed
) {
563 SetRenderSize (Size(0,0));
571 * FIXME I'm not happy with doing this here but until I come
572 * up with a better plan make sure that layout elements have
573 * been measured at least once
575 if (IsContainer () && !LayoutInformation::GetPreviousConstraint (this))
576 Measure (Size (finalRect
.width
, finalRect
.height
));
578 LayoutInformation::SetLayoutSlot (this, &finalRect
);
579 ClearValue (LayoutInformation::LayoutClipProperty
);
580 //LayoutInformation::SetLayoutClip (this, NULL);
582 this->dirty_flags
&= ~DirtyArrange
;
584 Thickness margin
= *GetMargin ();
585 Rect child_rect
= finalRect
.GrowBy (-margin
);
587 cairo_matrix_init_translate (&layout_xform
, child_rect
.x
, child_rect
.y
);
590 this->dirty_flags
&= ~DirtyArrange
;
592 Size
offer (child_rect
.width
, child_rect
.height
);
594 Size desired
= GetDesiredSize ().GrowBy (-margin
);
596 HorizontalAlignment horiz
= GetHorizontalAlignment ();
597 VerticalAlignment vert
= GetVerticalAlignment ();
599 if (horiz
!= HorizontalAlignmentStretch
)
600 offer
.width
= MIN (offer
.width
, desired
.width
);
602 if (vert
!= VerticalAlignmentStretch
)
603 offer
.height
= MIN (offer
.height
, desired
.height
);
605 offer
= ApplySizeConstraints (offer
);
608 response
= (*arrange_cb
)(offer
);
610 response
= ArrangeOverride (offer
);
612 /* XXX FIXME horrible hack */
613 UIElement
*parent
= GetVisualParent ();
614 bool in_layout
= IsLayoutContainer ();
617 if (!parent
|| parent
->Is (Type::CANVAS
))
620 Size old_size
= GetRenderSize ();
621 //Point *old_offset = LayoutInformation::GetVisualOffset (this);
622 ClearValue (LayoutInformation::VisualOffsetProperty
);
624 if (in_layout
&& GetUseLayoutRounding ()) {
625 response
.width
= floor (response
.width
);
626 response
.height
= floor (response
.height
);
629 SetActualWidth (response
.width
);
630 SetActualHeight (response
.height
);
632 response
= ApplySizeConstraints (response
);
633 Point
visual_offset (child_rect
.x
, child_rect
.y
);
635 if (GetVisualParent ()) {
637 case HorizontalAlignmentLeft
:
639 case HorizontalAlignmentRight
:
640 visual_offset
.x
+= child_rect
.width
- response
.width
;
642 case HorizontalAlignmentCenter
:
643 visual_offset
.x
+= (child_rect
.width
- response
.width
) * .5;
646 visual_offset
.x
+= MAX ((child_rect
.width
- response
.width
) * .5, 0);
651 case VerticalAlignmentTop
:
653 case VerticalAlignmentBottom
:
654 visual_offset
.y
+= child_rect
.height
- response
.height
;
656 case VerticalAlignmentCenter
:
657 visual_offset
.y
+= (child_rect
.height
- response
.height
) * .5;
660 visual_offset
.y
+= MAX ((child_rect
.height
- response
.height
) * .5, 0);
666 cairo_matrix_init_translate (&layout_xform
, visual_offset
.x
, visual_offset
.y
);
667 LayoutInformation::SetVisualOffset (this, &visual_offset
);
668 SetRenderSize (response
);
670 Rect layout_clip
= finalRect
;
671 layout_clip
.x
-= visual_offset
.x
;
672 layout_clip
.y
-= visual_offset
.y
;
674 layout_clip
= layout_clip
.GrowBy (-margin
);
675 RectangleGeometry
*rectangle
= new RectangleGeometry ();
676 rectangle
->SetRect (&layout_clip
);
677 LayoutInformation::SetLayoutClip (this, rectangle
);
680 if (old_size
!= response
) { // || (old_offset && *old_offset != visual_offset)) {
681 if (!LayoutInformation::GetLastRenderSize (this))
682 LayoutInformation::SetLastRenderSize (this, &old_size
);
684 // XXX what do we do with finalRect.x and y?
689 FrameworkElement::ArrangeOverride (Size finalSize
)
691 finalSize
= ApplySizeConstraints (finalSize
);
693 if (!IsLayoutContainer ())
696 Size arranged
= finalSize
;
698 VisualTreeWalker walker
= VisualTreeWalker (this);
699 while (UIElement
*child
= walker
.Step ()) {
700 if (child
->GetVisibility () != VisibilityVisible
)
703 Rect
childRect (0,0,finalSize
.width
,finalSize
.height
);
705 child
->Arrange (childRect
);
706 arranged
= child
->GetRenderSize ();
708 arranged
= arranged
.Max (finalSize
);
711 arranged
= arranged
.Max (finalSize
);
717 FrameworkElement::UpdateLayout ()
719 UIElement
*element
= this;
720 UIElement
*parent
= NULL
;
723 while ((parent
= element
->GetVisualParent ())) {
724 if (parent
->Is (Type::CANVAS
))
730 Surface
*surface
= element
->GetSurface ();
732 LOG_LAYOUT ("\nFrameworkElement::UpdateLayout: ");
733 List
*measure_list
= new List ();
734 List
*arrange_list
= new List ();
735 List
*size_list
= new List ();
736 bool updated
= false;
738 while (i
< MAX_LAYOUT_PASSES
) {
739 LOG_LAYOUT ("\u267c");
741 measure_list
->Clear (true);
742 arrange_list
->Clear (true);
743 size_list
->Clear (true);
746 DeepTreeWalker
measure_walker (element
);
747 while (FrameworkElement
*child
= (FrameworkElement
*)measure_walker
.Step ()) {
748 FrameworkElement
*parent
= (FrameworkElement
*)child
->GetVisualParent ();
750 if ((child
->flags
& UIElement::RENDER_VISIBLE
) == 0) {
751 measure_walker
.SkipBranch ();
755 if (child
->dirty_flags
& DirtyMeasure
) {
756 UIElement
*parent
= child
->GetVisualParent ();
757 if ((parent
&& !parent
->Is (Type::CANVAS
)) || child
->IsContainer ()) {
758 measure_list
->Append (new UIElementNode (child
));
759 //g_warning ("adding %p, %s", child, child->GetTypeName ());
760 } else if (!measure_list
->IsEmpty ()) {
761 measure_walker
.SkipBranch ();
765 if (!measure_list
->IsEmpty ())
768 if (child
->dirty_flags
& DirtyArrange
)
769 arrange_list
->Append (new UIElementNode (child
));
771 if (!arrange_list
->IsEmpty ())
774 if (child
->ReadLocalValue (LayoutInformation::LastRenderSizeProperty
))
775 size_list
->Append (new UIElementNode (child
));
777 if (!size_list
->IsEmpty ())
781 if (!measure_list
->IsEmpty ()) {
783 surface
->needs_measure
= false;
784 while (UIElementNode
* node
= (UIElementNode
*)measure_list
->First ()) {
785 measure_list
->Unlink (node
);
787 node
->uielement
->DoMeasure ();
788 //if (node->uielement->GetVisuaParent ()->dirty_flags & dirty_measure)
789 // node->Prepend (new UIElementNode (parent));
794 } else if (!arrange_list
->IsEmpty ()) {
796 surface
->needs_arrange
= false;
797 while (UIElementNode
*node
= (UIElementNode
*)arrange_list
->First ()) {
798 arrange_list
->Unlink (node
);
800 if (surface
&& surface
->needs_measure
) {
805 node
->uielement
->DoArrange ();
806 //if (node->uielement->GetVisuaParent ()->dirty_flags & dirty_arrange)
807 // node->Prepend (new UIElementNode (parent));
812 } else if (!size_list
->IsEmpty ()) {
813 while (UIElementNode
*node
= (UIElementNode
*)size_list
->First ()) {
814 if (surface
&& (surface
->needs_measure
|| surface
->needs_arrange
)) {
815 surface
->needs_measure
= surface
->needs_arrange
= false;
819 size_list
->Unlink (node
);
820 FrameworkElement
*fe
= (FrameworkElement
*) node
->uielement
;
823 Size
*last
= LayoutInformation::GetLastRenderSize (fe
);
825 SizeChangedEventArgs
*args
= new SizeChangedEventArgs (*last
, fe
->GetRenderSize ());
826 fe
->ClearValue (LayoutInformation::LastRenderSizeProperty
, false);
827 fe
->Emit (FrameworkElement::SizeChangedEvent
, args
);
831 } else if (updated
) {
832 Deployment::GetCurrent()->LayoutUpdated ();
841 if (i
>= MAX_LAYOUT_PASSES
) {
842 LOG_LAYOUT ("\n************** UpdateLayout Bailing Out after %d Passes *******************\n", i
);
844 LOG_LAYOUT (" (%d)\n", i
);
849 FrameworkElement::RegisterManagedOverrides (MeasureOverrideCallback measure_cb
, ArrangeOverrideCallback arrange_cb
,
850 GetDefaultTemplateCallback get_default_template_cb
, LoadedCallback loaded_cb
)
852 this->measure_cb
= measure_cb
;
853 this->arrange_cb
= arrange_cb
;
854 this->get_default_template_cb
= get_default_template_cb
;
855 this->loaded_cb
= loaded_cb
;
859 FrameworkElement::SetDefaultStyle (Style
*style
)
862 Application::GetCurrent()->ApplyStyle (this, style
);
863 default_style_applied
= true;
864 ((StylePropertyValueProvider
*)providers
[PropertyPrecedence_DefaultStyle
])->SealStyle (style
);
870 FrameworkElement::OnLoaded ()
872 UIElement::OnLoaded ();
879 FrameworkElement::ApplyTemplate ()
881 if (GetSubtreeObject ())
884 bool result
= DoApplyTemplate ();
891 FrameworkElement::DoApplyTemplate ()
893 UIElement
*e
= GetDefaultTemplate ();
896 e
->SetParent (this, &err
);
897 SetSubtreeObject (e
);
904 FrameworkElement::ElementRemoved (UIElement
*obj
)
906 if (GetSubtreeObject () == obj
) {
908 obj
->SetParent (NULL
, &e
);
909 SetSubtreeObject (NULL
);
911 UIElement::ElementRemoved (obj
);
915 FrameworkElement::GetDefaultTemplate ()
917 if (get_default_template_cb
)
918 return get_default_template_cb (this);