@@ -33,9 +33,11 @@ namespace lsp
3333 // Bind
3434 sLayout .bind(" layout" , this );
3535 sConstraints .bind(" size.constraints" , this );
36+ sAggregateSize .bind(" size.aggregate" , this );
3637 // Configure
3738 sLayout .set(0 .0f , 0 .0f , 0 .0f , 0 .0f );
3839 sConstraints .set_all(-1 );
40+ sAggregateSize .set(true );
3941 // Override
4042 sLayout .override ();
4143 sConstraints .override ();
@@ -47,11 +49,11 @@ namespace lsp
4749
4850 Align::Align (Display *dpy):
4951 WidgetContainer (dpy),
52+ vWidgets (&sProperties , &sIListener ),
5053 sLayout (&sProperties ),
51- sConstraints (&sProperties )
54+ sConstraints (&sProperties ),
55+ sAggregateSize (&sProperties )
5256 {
53- pWidget = NULL ;
54-
5557 pClass = &metadata;
5658 }
5759
@@ -67,8 +69,11 @@ namespace lsp
6769 if (result != STATUS_OK )
6870 return result;
6971
72+ sIListener .bind_all (this , on_add_widget, on_remove_widget);
73+
7074 sLayout .bind (" layout" , &sStyle );
7175 sConstraints .bind (" size.constraints" , &sStyle );
76+ sAggregateSize .bind (" size.aggregate" , &sStyle );
7277
7378 return STATUS_OK ;
7479 }
@@ -82,27 +87,69 @@ namespace lsp
8287
8388 void Align::do_destroy ()
8489 {
85- if (pWidget != NULL )
90+ // Unlink children
91+ for (size_t i=0 , n=vWidgets.size (); i<n; ++i)
92+ {
93+ // Get widget
94+ Widget * const w = vWidgets.get (i);
95+ if (w != NULL )
96+ unlink_widget (w);
97+ }
98+
99+ // Free list of children
100+ vWidgets.flush ();
101+ }
102+
103+ void Align::on_add_widget (void *obj, Property *prop, void *w)
104+ {
105+ Widget * const item = widget_ptrcast<Widget>(w);
106+ if (item == NULL )
107+ return ;
108+
109+ Align * const self = widget_ptrcast<Align>(obj);
110+ if (self != NULL )
111+ {
112+ item->set_parent (self);
113+ self->query_resize ();
114+ }
115+ }
116+
117+ void Align::on_remove_widget (void *obj, Property *prop, void *w)
118+ {
119+ Widget * const item = widget_ptrcast<Widget>(w);
120+ if (item == NULL )
121+ return ;
122+
123+ Align * const self = widget_ptrcast<Align>(obj);
124+ if (self != NULL )
86125 {
87- unlink_widget (pWidget );
88- pWidget = NULL ;
126+ self-> unlink_widget (item );
127+ self-> query_resize () ;
89128 }
90129 }
91130
92131 Widget *Align::find_widget (ssize_t x, ssize_t y)
93132 {
94- if ((pWidget == NULL ) || (!pWidget->is_visible_child_of (this )))
95- return NULL ;
133+ Widget * const w = current_widget ();
134+ return (w->inside (x, y)) ? w : NULL ;
135+ }
136+
137+ Widget *Align::current_widget ()
138+ {
139+ for (size_t i=0 , n=vWidgets.size (); i<n; ++i)
140+ {
141+ Widget * const w = vWidgets.get (i);
142+ if (w->is_visible_child_of (this ))
143+ return w;
144+ }
96145
97- return (pWidget-> inside (x, y)) ? pWidget : NULL ;
146+ return NULL ;
98147 }
99148
100149 void Align::property_changed (Property *prop)
101150 {
102151 WidgetContainer::property_changed (prop);
103- if (sLayout .is (prop))
104- query_resize ();
105- if (sConstraints .is (prop))
152+ if (prop->one_of (sLayout , sConstraints , sAggregateSize ))
106153 query_resize ();
107154 }
108155
@@ -111,12 +158,14 @@ namespace lsp
111158 if (nFlags & REDRAW_SURFACE )
112159 force = true ;
113160
161+ Widget * const widget = current_widget ();
162+
114163 // Initialize palette
115164 lsp::Color bg_color;
116165 get_actual_bg_color (bg_color);
117166
118167 // Draw background if child is invisible or not present
119- if ((pWidget == NULL ) || (!pWidget ->visibility ()->get ()))
168+ if ((widget == NULL ) || (!widget ->visibility ()->get ()))
120169 {
121170 s->clip_begin (area);
122171 s->fill_rect (bg_color, SURFMASK_NONE , 0 .0f , &sSize );
@@ -125,95 +174,109 @@ namespace lsp
125174 }
126175
127176 ws::rectangle_t xr;
128- pWidget ->get_rectangle (&xr);
177+ widget ->get_rectangle (&xr);
129178
130- if ((force) || (pWidget ->redraw_bg_pending ()))
179+ if ((force) || (widget ->redraw_bg_pending ()))
131180 {
132181 if (Size::overlap (area, &sSize ))
133182 {
134183 s->clip_begin (area);
135184 {
136- pWidget ->get_actual_bg_color (bg_color);
185+ widget ->get_actual_bg_color (bg_color);
137186 s->fill_frame (bg_color, SURFMASK_NONE , 0 .0f , &sSize , &xr);
138187 }
139188 s->clip_end ();
140189 }
141190 }
142191
143- if ((force) || (pWidget ->redraw_pending ()))
192+ if ((force) || (widget ->redraw_pending ()))
144193 {
145194 // Draw the child only if it is visible in the area
146195 if (Size::intersection (&xr, area))
147- pWidget ->render (s, &xr, force);
148- pWidget ->commit_redraw ();
196+ widget ->render (s, &xr, force);
197+ widget ->commit_redraw ();
149198 }
150199 }
151200
152201 status_t Align::add (Widget *widget)
153202 {
154- if ((widget == NULL ) || (widget == this ))
155- return STATUS_BAD_ARGUMENTS ;
156- if (pWidget != NULL )
157- return STATUS_ALREADY_EXISTS ;
158-
159- widget->set_parent (this );
160- pWidget = widget;
161- query_resize ();
162- return STATUS_OK ;
203+ return vWidgets.add (widget);
163204 }
164205
165206 status_t Align::remove (Widget *widget)
166207 {
167- if (pWidget != widget)
168- return STATUS_NOT_FOUND ;
169-
170- unlink_widget (pWidget);
171- pWidget = NULL ;
172- query_resize ();
173-
174- return STATUS_OK ;
208+ return vWidgets.premove (widget);
175209 }
176210
177211 void Align::size_request (ws::size_limit_t *r)
178212 {
179- float scaling = lsp_max (0 .0f , sScaling .get ());
213+ const float scaling = lsp_max (0 .0f , sScaling .get ());
214+
215+ // Estimate minimum size
216+ size_t count = 0 ;
180217
181- if ((pWidget == NULL ) || (!pWidget-> is_visible_child_of ( this ) ))
218+ if (sAggregateSize . get ( ))
182219 {
183- r->nMinWidth = -1 ;
184- r->nMinHeight = -1 ;
185- r->nMaxWidth = -1 ;
186- r->nMaxHeight = -1 ;
220+ ws::size_limit_t xr;
221+
222+ for (size_t i=0 , n=vWidgets.size (); i<n; ++i)
223+ {
224+ Widget * const w = vWidgets.get (i);
225+ if (w == NULL )
226+ continue ;
227+
228+ if ((count++) > 0 )
229+ {
230+ w->get_padded_size_limits (&xr);
231+ SizeConstraints::maximize (r, &xr);
232+ }
233+ else
234+ w->get_padded_size_limits (r);
235+ }
187236 }
188237 else
189238 {
190- pWidget->get_padded_size_limits (r);
191- r->nMaxWidth = -1 ;
192- r->nMaxHeight = -1 ;
239+ Widget * const w = current_widget ();
240+ if (w != NULL )
241+ {
242+ w->get_padded_size_limits (r);
243+ ++count;
244+ }
193245 }
194246
247+ // Fill size parameters
248+ if (count <= 0 )
249+ {
250+ r->nMinWidth = -1 ;
251+ r->nMinHeight = -1 ;
252+ }
253+
254+ r->nMaxWidth = -1 ;
255+ r->nMaxHeight = -1 ;
195256 r->nPreWidth = -1 ;
196257 r->nPreHeight = -1 ;
197258
259+ // Apply constraints
198260 sConstraints .apply (r, scaling);
199261 }
200262
201263 bool Align::realize (const ws::rectangle_t *r)
202264 {
203265// lsp_trace("width=%d, height=%d", int(r->nWidth), int(r->nHeight));
204- bool needs_redraw = WidgetContainer::realize (r );
266+ Widget * const widget = current_widget ( );
205267
206- if ((pWidget == NULL ) || (!pWidget->is_visible_child_of (this )))
268+ bool needs_redraw = WidgetContainer::realize (r);
269+ if (widget == NULL )
207270 return needs_redraw;
208271
209272 // Realize child widget
210273 ws::rectangle_t xr;
211274 ws::size_limit_t sr;
212275
213- pWidget ->get_padded_size_limits (&sr);
276+ widget ->get_padded_size_limits (&sr);
214277 sLayout .apply (&xr, r, &sr);
215- pWidget ->padding ()->enter (&xr, pWidget ->scaling ()->get ());
216- if (pWidget ->realize_widget (&xr))
278+ widget ->padding ()->enter (&xr, widget ->scaling ()->get ());
279+ if (widget ->realize_widget (&xr))
217280 needs_redraw = true ;
218281
219282 return needs_redraw;
0 commit comments