Skip to content

Commit 1441f38

Browse files
author
bjn
committed
Added functions to get values out of rect, point and view_stretch by axis.
Refactored the tile code so that the limit and layout method on vtile_element and htile_element call common templated code using that axis dependent code. Gives single code path for both.
1 parent b386261 commit 1441f38

File tree

4 files changed

+121
-101
lines changed

4 files changed

+121
-101
lines changed

lib/include/elements/base_view.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ namespace cycfi::elements
7373
{
7474
float x = 1.0;
7575
float y = 1.0;
76+
77+
constexpr float coord(bool is_x_axis) const {
78+
return is_x_axis ? x : y;
79+
}
80+
81+
constexpr float& coord(bool is_x_axis) {
82+
return is_x_axis ? x : y;
83+
}
7684
};
7785

7886
////////////////////////////////////////////////////////////////////////////

lib/include/elements/support/point.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ namespace cycfi { namespace elements
2424
constexpr point move(float dx, float dy) const;
2525
constexpr point move_to(float x, float y) const;
2626

27+
constexpr float coord(bool is_x_axis) const;
28+
constexpr float& coord(bool is_x_axis);
29+
2730
float x;
2831
float y;
2932
};
@@ -79,6 +82,16 @@ namespace cycfi { namespace elements
7982
r.y = y_;
8083
return r;
8184
}
85+
86+
inline constexpr float point::coord(bool is_x_axis) const
87+
{
88+
return is_x_axis ? x : y;
89+
}
90+
91+
constexpr float& point::coord(bool is_x_axis)
92+
{
93+
return is_x_axis ? x : y;
94+
}
8295
}}
8396

8497
#endif

lib/include/elements/support/rect.hpp

+32
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ namespace cycfi { namespace elements
5353
constexpr rect move_to(float x, float y) const;
5454
constexpr rect inset(float x_inset = 1.0, float y_inset = 1.0) const;
5555

56+
constexpr float axisDelta(bool is_x_axis) const;
57+
constexpr float axisMin(bool is_x_axis ) const;
58+
constexpr float axisMax(bool is_x_axis ) const;
59+
constexpr float& axisMin(bool is_x_axis );
60+
constexpr float& axisMax(bool is_x_axis );
61+
5662
float left;
5763
float top;
5864
float right;
@@ -208,6 +214,32 @@ namespace cycfi { namespace elements
208214
return r;
209215
}
210216

217+
218+
constexpr float rect::axisDelta(bool is_x_axis) const
219+
{
220+
return is_x_axis ? width() : height();
221+
}
222+
223+
constexpr float rect::axisMin(bool is_x_axis ) const
224+
{
225+
return is_x_axis ? left : top;
226+
}
227+
228+
constexpr float rect::axisMax(bool is_x_axis ) const
229+
{
230+
return is_x_axis ? right : bottom;
231+
}
232+
233+
constexpr float& rect::axisMin(bool is_x_axis )
234+
{
235+
return is_x_axis ? left : top;
236+
}
237+
238+
constexpr float& rect::axisMax(bool is_x_axis )
239+
{
240+
return is_x_axis ? right : bottom;
241+
}
242+
211243
constexpr bool is_valid(rect r)
212244
{
213245
return (r.left <= r.right) && (r.top <= r.bottom);

lib/src/element/tile.cpp

+68-101
Original file line numberDiff line numberDiff line change
@@ -90,68 +90,84 @@ namespace cycfi::elements
9090
std::sort(elements.begin(), elements.end(),
9191
[](layout_info lhs, layout_info rhs){ return lhs.index < rhs.index; });
9292
}
93-
}
9493

95-
////////////////////////////////////////////////////////////////////////////
96-
// Vertical Tiles
97-
////////////////////////////////////////////////////////////////////////////
98-
view_limits vtile_element::limits(basic_context const& ctx) const
99-
{
100-
view_limits limits{{0.0, 0.0}, {full_extent, 0.0}};
101-
for (std::size_t i = 0; i != size(); ++i)
94+
template<bool IS_X_AXIS, class TILE_ELEMENT>
95+
[[gnu::always_inline]] inline auto compute_limits(basic_context const& ctx, const TILE_ELEMENT &tile) -> view_limits
96+
{
97+
view_limits limits{{0.0, 0.0},
98+
{IS_X_AXIS ? 0.0 : full_extent,
99+
IS_X_AXIS ? full_extent : 0.0}};
100+
for (std::size_t i = 0; i != tile.size(); ++i)
102101
{
103-
auto el = at(i).limits(ctx);
102+
auto el = tile.at(i).limits(ctx);
104103

105-
limits.min.y += el.min.y;
106-
limits.max.y += el.max.y;
107-
clamp_min(limits.min.x, el.min.x);
108-
clamp_max(limits.max.x, el.max.x);
104+
limits.min.coord(IS_X_AXIS) += el.min.coord(IS_X_AXIS);
105+
limits.max.coord(IS_X_AXIS) += el.max.coord(IS_X_AXIS);
106+
clamp_min(limits.min.coord(! IS_X_AXIS), el.min.coord(! IS_X_AXIS));
107+
clamp_max(limits.max.coord(! IS_X_AXIS), el.max.coord(! IS_X_AXIS));
109108
}
110109

111-
clamp_min(limits.max.x, limits.min.x);
112-
clamp_max(limits.max.y, full_extent);
110+
clamp_min(limits.max.coord(! IS_X_AXIS), limits.min.coord(! IS_X_AXIS));
111+
clamp_max(limits.max.coord(IS_X_AXIS), full_extent);
113112
return limits;
114-
}
115-
116-
void vtile_element::layout(context const& ctx)
117-
{
118-
auto const sz = size();
119-
120-
// Collect min, max, and stretch information from each element.
121-
// Initially set the allocation sizes of each element to its minimum.
122-
std::vector<layout_info> info(sz);
123-
for (std::size_t i = 0; i != sz; ++i)
124-
{
125-
auto& elem = at(i);
113+
}
114+
115+
template<bool IS_X_AXIS, class TILE_ELEMENT>
116+
[[gnu::always_inline]] inline auto compute_layout(context const& ctx, TILE_ELEMENT &tile, std::vector<float> &tilePos) -> void
117+
{
118+
auto const sz = tile.size();
119+
120+
// Collect min, max, and stretch information from each element.
121+
// Initially set the allocation sizes of each element to its minimum.
122+
std::vector<layout_info> info(sz);
123+
for (std::size_t i = 0; i != sz; ++i)
124+
{
125+
auto& elem = tile.at(i);
126126
auto limits = elem.limits(ctx);
127-
info[i].stretch = elem.stretch().y;
128-
info[i].min = limits.min.y;
129-
info[i].max = limits.max.y;
130-
info[i].alloc = limits.min.y;
127+
info[i].stretch = elem.stretch().coord(IS_X_AXIS);
128+
info[i].min = limits.min.coord(IS_X_AXIS);
129+
info[i].max = limits.max.coord(IS_X_AXIS);
130+
info[i].alloc = limits.min.coord(IS_X_AXIS);
131131
info[i].index = i;
132-
}
133-
134-
auto const left = ctx.bounds.left;
135-
auto const right = ctx.bounds.right;
136-
auto const top = ctx.bounds.top;
137-
auto const height = ctx.bounds.height();
138-
// Compute the best fit for all elements
139-
allocate(height, info);
140-
141-
// Now we have the final layout. We can now layout the individual
142-
// elements.
143-
_tiles.resize(sz);
144-
auto curr = 0.0f;
145-
for (std::size_t i = 0; i != sz; ++i)
146-
{
147-
_tiles[i] = curr + info[i].alloc;
132+
}
133+
134+
auto const otherMin = ctx.bounds.axisMin(not IS_X_AXIS);
135+
auto const otherMax = ctx.bounds.axisMax(not IS_X_AXIS);
136+
auto const myMin = ctx.bounds.axisMin(IS_X_AXIS);
137+
auto const myDelta = ctx.bounds.axisDelta(IS_X_AXIS);
138+
// Compute the best fit for all elements
139+
allocate(myDelta, info);
140+
141+
// Now we have the final layout. We can now layout the individual
142+
// elements.
143+
tilePos.resize(sz);
144+
auto curr = 0.0f;
145+
for (std::size_t i = 0; i != sz; ++i)
146+
{
147+
tilePos[i] = curr + info[i].alloc;
148148
auto const prev = curr;
149149
curr += info[i].alloc;
150150

151-
auto& elem = at(i);
152-
rect ebounds = {left, prev+top, right, curr+top};
151+
auto& elem = tile.at(i);
152+
auto ebounds = IS_X_AXIS
153+
? rect{prev+myMin, otherMin, curr+myMin, otherMax}
154+
: rect{otherMin, prev+myMin, otherMax, curr+myMin};
153155
elem.layout(context{ctx, &elem, ebounds});
154-
}
156+
}
157+
}
158+
}
159+
160+
////////////////////////////////////////////////////////////////////////////
161+
// Vertical Tiles
162+
////////////////////////////////////////////////////////////////////////////
163+
view_limits vtile_element::limits(basic_context const& ctx) const
164+
{
165+
return compute_limits<false>(ctx, *this);
166+
}
167+
168+
void vtile_element::layout(context const& ctx)
169+
{
170+
compute_layout<false>(ctx, *this, _tiles);
155171
}
156172

157173
void vtile_element::draw(context const& ctx)
@@ -176,61 +192,12 @@ namespace cycfi::elements
176192
////////////////////////////////////////////////////////////////////////////
177193
view_limits htile_element::limits(basic_context const& ctx) const
178194
{
179-
view_limits limits{{0.0, 0.0}, {0.0, full_extent}};
180-
for (std::size_t i = 0; i != size(); ++i)
181-
{
182-
auto el = at(i).limits(ctx);
183-
184-
limits.min.x += el.min.x;
185-
limits.max.x += el.max.x;
186-
clamp_min(limits.min.y, el.min.y);
187-
clamp_max(limits.max.y, el.max.y);
188-
}
189-
190-
clamp_min(limits.max.y, limits.min.y);
191-
clamp_max(limits.max.x, full_extent);
192-
return limits;
195+
return compute_limits<true>(ctx, *this);
193196
}
194197

195198
void htile_element::layout(context const& ctx)
196199
{
197-
auto const sz = size();
198-
199-
// Collect min, max, and stretch information from each element.
200-
// Initially set the allocation sizes of each element to its minimum.
201-
std::vector<layout_info> info(sz);
202-
for (std::size_t i = 0; i != sz; ++i)
203-
{
204-
auto& elem = at(i);
205-
auto limits = elem.limits(ctx);
206-
info[i].stretch = elem.stretch().x;
207-
info[i].min = limits.min.x;
208-
info[i].max = limits.max.x;
209-
info[i].alloc = limits.min.x;
210-
info[i].index = i;
211-
}
212-
213-
auto const top = ctx.bounds.top;
214-
auto const bottom = ctx.bounds.bottom;
215-
auto const left = ctx.bounds.left;
216-
auto const width = ctx.bounds.width();
217-
// Compute the best fit for all elements
218-
allocate(width, info);
219-
220-
// Now we have the final layout. We can now layout the individual
221-
// elements.
222-
_tiles.resize(sz);
223-
auto curr = 0.0f;
224-
for (std::size_t i = 0; i != sz; ++i)
225-
{
226-
_tiles[i] = curr + info[i].alloc;
227-
auto const prev = curr;
228-
curr += info[i].alloc;
229-
230-
auto& elem = at(i);
231-
rect ebounds = {prev+left, top, curr+left, bottom};
232-
elem.layout(context{ctx, &elem, ebounds});
233-
}
200+
compute_layout<true>(ctx, *this, _tiles);
234201
}
235202

236203
void htile_element::draw(context const& ctx)

0 commit comments

Comments
 (0)