Fix ui::label size constraints
This commit is contained in:
parent
3c851dfd60
commit
d16a71012d
2 changed files with 36 additions and 20 deletions
|
|
@ -84,6 +84,7 @@ namespace psemek::ui
|
||||||
mutable std::optional<cached_state> cached_state_;
|
mutable std::optional<cached_state> cached_state_;
|
||||||
|
|
||||||
void update_cached_state() const;
|
void update_cached_state() const;
|
||||||
|
cached_state cached_state_for(geom::box<float, 2> const & bbox) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,11 @@ namespace psemek::ui
|
||||||
|
|
||||||
geom::box<float, 2> label::size_constraints() const
|
geom::box<float, 2> label::size_constraints() const
|
||||||
{
|
{
|
||||||
if (!cached_state_)
|
|
||||||
update_cached_state();
|
|
||||||
|
|
||||||
static float const inf = std::numeric_limits<float>::infinity();
|
static float const inf = std::numeric_limits<float>::infinity();
|
||||||
return {{{cached_state_->size[0], inf}, {cached_state_->size[1], inf}}};
|
|
||||||
|
auto state = cached_state_for({{{0.f, inf}, {0.f, inf}}});
|
||||||
|
|
||||||
|
return {{{state.size[0], inf}, {state.size[1], inf}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
void label::draw(painter & p) const
|
void label::draw(painter & p) const
|
||||||
|
|
@ -82,15 +82,20 @@ namespace psemek::ui
|
||||||
|
|
||||||
void label::update_cached_state() const
|
void label::update_cached_state() const
|
||||||
{
|
{
|
||||||
cached_state_ = cached_state{};
|
cached_state_ = cached_state_for(shape_.box);
|
||||||
|
}
|
||||||
|
|
||||||
if (text_.empty()) return;
|
label::cached_state label::cached_state_for(geom::box<float, 2> const & bbox) const
|
||||||
|
{
|
||||||
|
auto state = cached_state{};
|
||||||
|
|
||||||
|
if (text_.empty()) return state;
|
||||||
|
|
||||||
auto st = style();
|
auto st = style();
|
||||||
if (!st) return;
|
if (!st) return state;
|
||||||
if (!st->font) return;
|
if (!st->font) return state;
|
||||||
|
|
||||||
cached_state_->font = st->font.get();
|
state.font = st->font.get();
|
||||||
|
|
||||||
shape_options opts;
|
shape_options opts;
|
||||||
opts.scale = st->text_scale;
|
opts.scale = st->text_scale;
|
||||||
|
|
@ -100,14 +105,17 @@ namespace psemek::ui
|
||||||
for (auto const & g : glyphs)
|
for (auto const & g : glyphs)
|
||||||
raw_bbox |= g.position;
|
raw_bbox |= g.position;
|
||||||
|
|
||||||
std::size_t max_lines = 1;
|
std::size_t max_lines;
|
||||||
|
|
||||||
switch (multiline_)
|
switch (multiline_)
|
||||||
{
|
{
|
||||||
case multiline_mode::none:
|
case multiline_mode::none:
|
||||||
|
max_lines = 1;
|
||||||
break;
|
break;
|
||||||
case multiline_mode::minimize_lines:
|
case multiline_mode::minimize_lines:
|
||||||
max_lines = std::max(1.f, std::floor(shape_.box[1].length() / st->font->size()[1] / st->text_scale));
|
max_lines = std::isfinite(bbox[1].length())
|
||||||
|
? std::max<std::size_t>(1, std::floor(bbox[1].length() / st->font->size()[1] / st->text_scale))
|
||||||
|
: std::numeric_limits<std::size_t>::max();
|
||||||
break;
|
break;
|
||||||
case multiline_mode::minimize_area:
|
case multiline_mode::minimize_area:
|
||||||
throw std::runtime_error("multiline_mode::minimize_area is not supported yet");
|
throw std::runtime_error("multiline_mode::minimize_area is not supported yet");
|
||||||
|
|
@ -136,7 +144,7 @@ namespace psemek::ui
|
||||||
|
|
||||||
x_range |= glyphs[line_end].position[0];
|
x_range |= glyphs[line_end].position[0];
|
||||||
|
|
||||||
if (x_range.length() > shape_.box[0].length())
|
if (x_range.length() > bbox[0].length())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++line_end;
|
++line_end;
|
||||||
|
|
@ -190,37 +198,41 @@ namespace psemek::ui
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float max_line_size = 0.f;
|
||||||
|
|
||||||
for (std::size_t l = 0; l < lines.size(); ++l)
|
for (std::size_t l = 0; l < lines.size(); ++l)
|
||||||
{
|
{
|
||||||
geom::interval<float> x_range;
|
geom::interval<float> x_range;
|
||||||
for (std::size_t i = lines[l].first; i < lines[l].second; ++i)
|
for (std::size_t i = lines[l].first; i < lines[l].second; ++i)
|
||||||
x_range |= glyphs[i].position[0];
|
x_range |= glyphs[i].position[0];
|
||||||
|
|
||||||
|
max_line_size = std::max(max_line_size, x_range.length());
|
||||||
|
|
||||||
geom::vector<float, 2> offset;
|
geom::vector<float, 2> offset;
|
||||||
|
|
||||||
switch (halign_)
|
switch (halign_)
|
||||||
{
|
{
|
||||||
case halignment::left:
|
case halignment::left:
|
||||||
offset[0] = shape_.box[0].min - x_range.min;
|
offset[0] = bbox[0].min - x_range.min;
|
||||||
break;
|
break;
|
||||||
case halignment::center:
|
case halignment::center:
|
||||||
offset[0] = shape_.box[0].center() - x_range.length() / 2.f - x_range.min;
|
offset[0] = bbox[0].center() - x_range.length() / 2.f - x_range.min;
|
||||||
break;
|
break;
|
||||||
case halignment::right:
|
case halignment::right:
|
||||||
offset[0] = shape_.box[0].max - x_range.length() - x_range.min;
|
offset[0] = bbox[0].max - x_range.length() - x_range.min;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (valign_)
|
switch (valign_)
|
||||||
{
|
{
|
||||||
case valignment::top:
|
case valignment::top:
|
||||||
offset[1] = shape_.box[1].min + l * st->text_scale * st->font->size()[1];
|
offset[1] = bbox[1].min + l * st->text_scale * st->font->size()[1];
|
||||||
break;
|
break;
|
||||||
case valignment::center:
|
case valignment::center:
|
||||||
offset[1] = shape_.box[1].center() + (l - lines.size() / 2.f) * st->text_scale * st->font->size()[1];
|
offset[1] = bbox[1].center() + (l - lines.size() / 2.f) * st->text_scale * st->font->size()[1];
|
||||||
break;
|
break;
|
||||||
case valignment::bottom:
|
case valignment::bottom:
|
||||||
offset[1] = shape_.box[1].max + (l - lines.size() * 1.f) * st->text_scale * st->font->size()[1];
|
offset[1] = bbox[1].max + (l - lines.size() * 1.f) * st->text_scale * st->font->size()[1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -228,8 +240,11 @@ namespace psemek::ui
|
||||||
glyphs[i].position += offset;
|
glyphs[i].position += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
cached_state_->glyphs = std::move(glyphs);
|
state.glyphs = std::move(glyphs);
|
||||||
cached_state_->size = raw_bbox.dimensions();
|
state.size[0] = max_line_size;
|
||||||
|
state.size[1] = lines.size() * st->text_scale * st->font->size()[1];
|
||||||
|
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue