1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright 2007 Novell, Inc. (http://www.novell.com)
7 * See the LICENSE file included with the distribution for details.
19 #include "thickness.h"
23 SetObjectType (Type::BORDER
);
27 Border::MeasureOverride (Size availableSize
)
29 Size desired
= Size (0,0);
30 Size specified
= Size (GetWidth (), GetHeight ());
32 availableSize
= availableSize
.Max (specified
);
33 availableSize
= availableSize
.Min (specified
);
35 Thickness border
= *GetPadding () + *GetBorderThickness ();
37 // Get the desired size of our child, and include any margins we set
38 VisualTreeWalker walker
= VisualTreeWalker (this);
39 while (UIElement
*child
= walker
.Step ()) {
40 if (child
->GetVisibility () != VisibilityVisible
)
43 child
->Measure (availableSize
.GrowBy (-border
));
44 desired
= child
->GetDesiredSize ();
47 desired
= desired
.GrowBy (border
);
49 desired
= desired
.Min (availableSize
);
50 desired
= desired
.Max (specified
);
51 desired
= desired
.Min (specified
);
57 Border::ArrangeOverride (Size finalSize
)
59 Thickness border
= *GetPadding () + *GetBorderThickness ();
61 Size specified
= Size (GetWidth (), GetHeight ());
63 finalSize
= finalSize
.Max (specified
);
64 finalSize
= finalSize
.Min (specified
);
66 Size arranged
= finalSize
;
68 VisualTreeWalker walker
= VisualTreeWalker (this);
69 while (UIElement
*child
= walker
.Step ()) {
70 if (child
->GetVisibility () != VisibilityVisible
)
73 Size desired
= child
->GetDesiredSize ();
74 Rect
childRect (0,0,finalSize
.width
,finalSize
.height
);
76 childRect
= childRect
.GrowBy (-border
);
78 if (GetHorizontalAlignment () != HorizontalAlignmentStretch
&& isnan (GetWidth ()))
79 childRect
.width
= MIN (desired
.width
, childRect
.width
);
81 if (GetVerticalAlignment () != VerticalAlignmentStretch
&& isnan (GetHeight ()))
82 childRect
.height
= MIN (desired
.height
, childRect
.height
);
84 child
->Arrange (childRect
);
85 arranged
= child
->GetRenderSize ();
86 arranged
= arranged
.GrowBy (border
);
88 if (GetHorizontalAlignment () == HorizontalAlignmentStretch
|| !isnan (GetWidth ()))
89 arranged
.width
= MAX (arranged
.width
, finalSize
.width
);
91 if (GetVerticalAlignment () == VerticalAlignmentStretch
|| !isnan (GetHeight()))
92 arranged
.height
= MAX (arranged
.height
, finalSize
.height
);
99 Border::Render (cairo_t
*cr
, Region
*region
, bool path_only
)
101 Brush
*background
= GetBackground ();
102 Brush
*border_brush
= GetBorderBrush ();
104 cairo_set_matrix (cr
, &absolute_xform
);
107 Geometry
*clip
= path_only
? NULL
: LayoutInformation::GetLayoutClip (this);
114 CornerRadius
*round
= GetCornerRadius ();
115 CornerRadius adjusted
= CornerRadius (0);
116 Thickness thickness
= *GetBorderThickness ();
117 Rect paint_border
= extents
;
118 Rect paint_background
= paint_border
.GrowBy (-thickness
);
122 adjusted
.topLeft
= MAX (round
->topLeft
- MAX (thickness
.left
, thickness
.top
), 0);
123 adjusted
.topRight
= MAX (round
->topRight
- MAX (thickness
.right
, thickness
.top
), 0);
124 adjusted
.bottomRight
= MAX (round
->bottomRight
- MAX (thickness
.right
, thickness
.bottom
), 0);
125 adjusted
.bottomLeft
= MAX (round
->bottomLeft
- MAX (thickness
.left
, thickness
.bottom
), 0);
129 * NOTE filling this way can leave alpha artifacts between the border fill and bg fill
130 * but some simple inspection of the ms results make me think that is what happens there
134 cairo_set_fill_rule (cr
, CAIRO_FILL_RULE_EVEN_ODD
);
137 border_brush
->SetupBrush (cr
, paint_border
);
140 paint_border
.Draw (cr
, round
);
141 paint_background
.Draw (cr
, round
? &adjusted
: NULL
);
144 border_brush
->Fill (cr
);
148 background
->SetupBrush (cr
, paint_background
);
150 paint_background
.Draw (cr
, round
? &adjusted
: NULL
);
153 background
->Fill (cr
);
161 Border::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
163 if (args
->GetProperty ()->GetOwnerType() != Type::BORDER
) {
164 FrameworkElement::OnPropertyChanged (args
, error
);
168 if (args
->GetId () == Border::ChildProperty
){
169 if (args
->GetOldValue() && args
->GetOldValue()->AsUIElement()) {
170 ElementRemoved (args
->GetOldValue()->AsUIElement ());
171 if (args
->GetOldValue()->Is(Type::FRAMEWORKELEMENT
)) {
172 args
->GetOldValue()->AsFrameworkElement()->SetLogicalParent (NULL
, error
);
178 if (args
->GetNewValue() && args
->GetNewValue()->AsUIElement()) {
179 ElementAdded (args
->GetNewValue()->AsUIElement ());
180 if (args
->GetNewValue()->Is(Type::FRAMEWORKELEMENT
)) {
181 FrameworkElement
*fwe
= args
->GetNewValue()->AsFrameworkElement ();
182 if (fwe
->GetLogicalParent() && fwe
->GetLogicalParent() != this) {
183 MoonError::FillIn (error
, MoonError::ARGUMENT
, "Content is already a child of another element");
187 args
->GetNewValue()->AsFrameworkElement()->SetLogicalParent (this, error
);
193 SetSubtreeObject (args
->GetNewValue() ? args
->GetNewValue()->AsUIElement() : NULL
);
196 InvalidateMeasure ();
198 else if (args
->GetId () == Border::PaddingProperty
199 || args
->GetId () == Border::BorderThicknessProperty
) {
200 InvalidateMeasure ();
201 } else if (args
->GetId () == Border::BackgroundProperty
) {
204 NotifyListenersOfPropertyChange (args
, error
);
208 Border::InsideObject (cairo_t
*cr
, double x
, double y
)
210 if (GetBackground ())
211 return FrameworkElement::InsideObject (cr
, x
, y
);
217 Border::HitTest (cairo_t
*cr
, Rect r
, List
*uielement_list
)