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.
18 #include "collection.h"
20 #include "deployment.h"
24 SetObjectType (Type::PANEL
);
27 SetSubtreeObject (GetChildren());
34 #define DEBUG_BOUNDS 0
38 static void space (int n
)
40 for (int i
= 0; i
< n
; i
++)
43 static int levelb
= 0;
47 Panel::ComputeBounds ()
52 printf ("Panel: Enter ComputeBounds (%s)\n", GetName());
55 // Clear the previous values
56 extents
= bounds
= bounds_with_children
= Rect ();
58 VisualTreeWalker walker
= VisualTreeWalker (this);
59 while (UIElement
*item
= walker
.Step ()) {
61 // if the item isn't drawn, skip it
62 if (!item
->GetRenderVisible ())
65 Rect r
= item
->GetSubtreeBounds ();
66 r
= IntersectBoundsWithClipPath (r
, true);
70 printf ("Item (%s, %s) bounds %g %g %g %g\n", item
->GetName (), item
->GetTypeName (),
71 r
.x
, r
.y
, r
.width
, r
.height
);
73 bounds_with_children
= bounds_with_children
.Union (r
);
76 Brush
*bg
= GetBackground();
78 extents
= Rect (0,0,GetActualWidth (),GetActualHeight ());
79 bounds
= IntersectBoundsWithClipPath (extents
, false).Transform (&absolute_xform
);
80 bounds_with_children
= bounds_with_children
.Union (bounds
);
85 printf ("Panel: Leave ComputeBounds (%g %g %g %g)\n",
86 bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
88 printf ("Panel: Leave ComputeBounds (%g %g %g %g)\n",
89 bounds_with_children
.x
, bounds_with_children
.y
, bounds_with_children
.width
, bounds_with_children
.height
);
95 Panel::ShiftPosition (Point p
)
97 double dx
= p
.x
- bounds
.x
;
98 double dy
= p
.y
- bounds
.y
;
100 // need to do this after computing the delta
101 FrameworkElement::ShiftPosition (p
);
103 bounds_with_children
.x
+= dx
;
104 bounds_with_children
.y
+= dy
;
107 //#define DEBUG_INVALIDATE 1
110 Panel::Render (cairo_t
*cr
, Region
*region
, bool path_only
)
112 Brush
*background
= GetBackground ();
114 cairo_set_matrix (cr
, &absolute_xform
);
116 Size
framework (GetActualWidth (), GetActualHeight ());
117 framework
= ApplySizeConstraints (framework
);
118 Rect area
= Rect (0.0, 0.0, framework
.width
, framework
.height
);
122 RenderLayoutClip (cr
);
127 if (background
&& area
.width
> 0 && area
.height
> 0 && !path_only
) {
128 background
->SetupBrush (cr
, area
);
129 background
->Fill (cr
);
135 Panel::GetCoverageBounds ()
137 Brush
*background
= GetBackground ();
139 if (background
&& background
->IsOpaque ())
146 Panel::InsideObject (cairo_t
*cr
, double x
, double y
)
148 if (GetBackground ())
149 return FrameworkElement::InsideObject (cr
, x
, y
);
155 Panel::EmptyBackground ()
157 return GetBackground () == NULL
;
161 Panel::MeasureOverride (Size availableSize
)
163 Size result
= Size (0,0);
168 Panel::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
170 if (args
->GetProperty ()->GetOwnerType() != Type::PANEL
) {
171 FrameworkElement::OnPropertyChanged (args
, error
);
175 if (args
->GetId () == Panel::BackgroundProperty
) {
176 /* several of the bounds values are conditional on having a brush */
179 } else if (args
->GetId () == Panel::ChildrenProperty
) {
180 Collection
*collection
;
182 SetSubtreeObject (args
->GetNewValue() ? args
->GetNewValue()->AsCollection() : NULL
);
184 if (args
->GetOldValue()) {
185 collection
= args
->GetOldValue()->AsCollection ();
186 for (int i
= 0; i
< collection
->GetCount (); i
++)
187 ElementRemoved (collection
->GetValueAt (i
)->AsUIElement());
190 if (args
->GetNewValue()) {
191 collection
= args
->GetNewValue()->AsCollection ();
192 for (int i
= 0; i
< collection
->GetCount (); i
++)
193 ElementAdded (collection
->GetValueAt (i
)->AsUIElement ());
199 NotifyListenersOfPropertyChange (args
, error
);
203 Panel::OnSubPropertyChanged (DependencyProperty
*prop
, DependencyObject
*obj
, PropertyChangedEventArgs
*subobj_args
)
205 if (prop
&& prop
->GetId () == Panel::BackgroundProperty
) {
208 FrameworkElement::OnSubPropertyChanged (prop
, obj
, subobj_args
);
213 Panel::OnCollectionChanged (Collection
*col
, CollectionChangedEventArgs
*args
)
215 if (col
== GetChildren ()) {
218 switch (args
->GetChangedAction()) {
219 case CollectionChangedActionReplace
:
220 if (args
->GetOldItem()->Is(GetDeployment (), Type::FRAMEWORKELEMENT
))
221 args
->GetOldItem()->AsFrameworkElement()->SetLogicalParent (NULL
, &error
/* XXX unused */);
222 ElementRemoved (args
->GetOldItem()->AsUIElement ());
223 // now fall thru to Add
224 case CollectionChangedActionAdd
:
225 if (args
->GetNewItem()->Is(GetDeployment (), Type::FRAMEWORKELEMENT
))
226 args
->GetNewItem()->AsFrameworkElement()->SetLogicalParent (this, &error
/* XXX unused */);
227 ElementAdded (args
->GetNewItem()->AsUIElement ());
229 case CollectionChangedActionRemove
:
230 if (args
->GetOldItem()->Is(GetDeployment (), Type::FRAMEWORKELEMENT
))
231 args
->GetOldItem()->AsFrameworkElement()->SetLogicalParent (NULL
, &error
/* XXX unused */);
232 ElementRemoved (args
->GetOldItem()->AsUIElement ());
234 case CollectionChangedActionClearing
:
235 for (int i
= 0; i
< col
->GetCount (); i
++) {
236 UIElement
*ui
= col
->GetValueAt (i
)->AsUIElement ();
237 if (ui
->Is(Type::FRAMEWORKELEMENT
))
238 ((FrameworkElement
*)ui
)->SetLogicalParent (NULL
, &error
/* XXX unused */);
242 case CollectionChangedActionCleared
:
243 // nothing needed here.
247 FrameworkElement::OnCollectionChanged (col
, args
);
255 FrameworkElement::OnLoaded ();
258 // queue a resort based on ZIndex
259 GetDeployment ()->GetSurface ()->AddDirtyElement (this, DirtyChildrenZIndices
);
264 Panel::ElementAdded (UIElement
*item
)
266 FrameworkElement::ElementAdded (item
);
269 // queue a resort based on ZIndex
270 GetDeployment ()->GetSurface ()->AddDirtyElement (this, DirtyChildrenZIndices
);
275 Panel::ElementRemoved (UIElement
*item
)
277 FrameworkElement::ElementRemoved (item
);
280 // queue a resort based on ZIndex
281 GetDeployment ()->GetSurface ()->AddDirtyElement (this, DirtyChildrenZIndices
);
287 Panel::OnCollectionItemChanged (Collection
*col
, DependencyObject
*obj
, PropertyChangedEventArgs
*args
)
289 if (col
== GetChildren()) {
290 // if a child changes its ZIndex property we need to resort our Children
291 if (args
->GetId () == Canvas::ZIndexProperty
) {
292 ((UIElement
*) obj
)->Invalidate ();
294 // queue a resort based on ZIndex
295 GetDeployment ()->GetSurface ()->AddDirtyElement (this, DirtyChildrenZIndices
);
301 FrameworkElement::OnCollectionItemChanged (col
, obj
, args
);