127 lines
2.4 KiB
C++
127 lines
2.4 KiB
C++
#include <psemek/ui/label.hpp>
|
|
|
|
namespace psemek::ui
|
|
{
|
|
|
|
void label::set_text(std::string text)
|
|
{
|
|
text_ = std::move(text);
|
|
on_state_changed();
|
|
}
|
|
|
|
void label::set_halign(halignment value)
|
|
{
|
|
halign_ = value;
|
|
on_state_changed();
|
|
}
|
|
|
|
void label::set_valign(valignment value)
|
|
{
|
|
valign_ = value;
|
|
on_state_changed();
|
|
}
|
|
|
|
void label::set_multiline(multiline_mode value)
|
|
{
|
|
multiline_ = value;
|
|
on_state_changed();
|
|
}
|
|
|
|
void label::set_overflow(overflow_mode value)
|
|
{
|
|
overflow_ = value;
|
|
on_state_changed();
|
|
}
|
|
|
|
void label::reshape(geom::box<float, 2> const & bbox)
|
|
{
|
|
shape_.box = bbox;
|
|
cached_state_.reset();
|
|
}
|
|
|
|
geom::box<float, 2> label::size_constraints() const
|
|
{
|
|
if (!cached_state_)
|
|
update_cached_state();
|
|
|
|
static float const inf = std::numeric_limits<float>::infinity();
|
|
return {{{cached_state_->size[0], inf}, {cached_state_->size[1], inf}}};
|
|
}
|
|
|
|
void label::draw(painter & p) const
|
|
{
|
|
if (!cached_state_)
|
|
update_cached_state();
|
|
|
|
if (!cached_state_->font) return;
|
|
|
|
auto st = style();
|
|
if (!st) return;
|
|
|
|
for (auto & g : cached_state_->glyphs)
|
|
p.draw_glyph(*(cached_state_->font), g.character, g.position, st->text_color);
|
|
}
|
|
|
|
void label::on_state_changed()
|
|
{
|
|
cached_state_.reset();
|
|
post_reshape();
|
|
}
|
|
|
|
void label::update_cached_state() const
|
|
{
|
|
cached_state_ = cached_state{};
|
|
|
|
if (text_.empty()) return;
|
|
|
|
auto st = style();
|
|
if (!st) return;
|
|
if (!st->font) return;
|
|
|
|
cached_state_->font = st->font.get();
|
|
|
|
shape_options opts;
|
|
opts.scale = st->text_scale;
|
|
cached_state_->glyphs = st->font->shape(text_, opts);
|
|
|
|
geom::box<float, 2> bbox;
|
|
for (auto const & g : cached_state_->glyphs)
|
|
bbox |= g.position;
|
|
|
|
int lines = 1;
|
|
|
|
geom::vector<float, 2> offset;
|
|
|
|
switch (halign_)
|
|
{
|
|
case halignment::left:
|
|
offset[0] = shape_.box[0].min;
|
|
break;
|
|
case halignment::center:
|
|
offset[0] = shape_.box[0].center() - bbox[0].length() / 2.f;
|
|
break;
|
|
case halignment::right:
|
|
offset[0] = shape_.box[0].max - bbox[0].length();
|
|
break;
|
|
}
|
|
|
|
switch (valign_)
|
|
{
|
|
case valignment::top:
|
|
offset[1] = shape_.box[1].min;
|
|
break;
|
|
case valignment::center:
|
|
offset[1] = shape_.box[1].center() - lines * st->text_scale * st->font->size()[1] / 2.f;
|
|
break;
|
|
case valignment::bottom:
|
|
offset[1] = shape_.box[1].max - lines * st->text_scale * st->font->size()[1];
|
|
break;
|
|
}
|
|
|
|
for (auto & g : cached_state_->glyphs)
|
|
g.position += offset;
|
|
|
|
cached_state_->size = bbox.dimensions();
|
|
}
|
|
|
|
}
|