Skip to content

Commit e433ed4

Browse files
committed
Added size aggregation for Group and Align widgets
1 parent a627f09 commit e433ed4

4 files changed

Lines changed: 176 additions & 84 deletions

File tree

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
=== 1.0.34 ===
66
* Added size aggregation for TabGroup and ComboGroup widgets.
7+
* Added size aggregation for Group and Align widgets.
78
* Updated build system: ASAN, CROSS_COMPILE, DEBUG, DEVEL, PROFILE, STRICT,
89
TEST, TRACE makefile flags replaced with 'asan', 'crosscompile', 'debug',
910
'devel', 'profile', 'strict', 'test' and 'trace' FEATURE flags.

include/lsp-plug.in/tk/widgets/containers/Align.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace lsp
3636
LSP_TK_STYLE_DEF_BEGIN(Align, WidgetContainer)
3737
prop::Layout sLayout;
3838
prop::SizeConstraints sConstraints;
39+
prop::Boolean sAggregateSize;
3940
LSP_TK_STYLE_DEF_END
4041
}
4142

@@ -47,15 +48,22 @@ namespace lsp
4748
class Align: public WidgetContainer
4849
{
4950
public:
50-
static const w_class_t metadata;
51+
static const w_class_t metadata;
5152

5253
protected:
53-
Widget *pWidget;
54-
prop::Layout sLayout;
55-
prop::SizeConstraints sConstraints;
54+
prop::WidgetList<Widget> vWidgets;
55+
prop::Layout sLayout;
56+
prop::SizeConstraints sConstraints;
57+
prop::Boolean sAggregateSize;
58+
prop::CollectionListener sIListener;
5659

5760
protected:
5861
void do_destroy();
62+
Widget *current_widget();
63+
64+
protected:
65+
static void on_add_widget(void *obj, Property *prop, void *w);
66+
static void on_remove_widget(void *obj, Property *prop, void *w);
5967

6068
protected:
6169
virtual Widget *find_widget(ssize_t x, ssize_t y) override;
@@ -76,8 +84,10 @@ namespace lsp
7684
virtual void destroy() override;
7785

7886
public:
87+
LSP_TK_PROPERTY(WidgetList<Widget>, widgets, &vWidgets)
7988
LSP_TK_PROPERTY(Layout, layout, &sLayout)
8089
LSP_TK_PROPERTY(SizeConstraints, constraints, &sConstraints)
90+
LSP_TK_PROPERTY(Boolean, aggregate_size, &sAggregateSize)
8191

8292
public:
8393
virtual void render(ws::ISurface *s, const ws::rectangle_t *area, bool force) override;

src/main/widgets/containers/Align.cpp

Lines changed: 113 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)