Make style members optional
This commit is contained in:
parent
f878321628
commit
d0a117adf4
6 changed files with 84 additions and 63 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
#include <psemek/ui/font.hpp>
|
#include <psemek/ui/font.hpp>
|
||||||
#include <psemek/ui/frame.hpp>
|
#include <psemek/ui/frame.hpp>
|
||||||
#include <psemek/ui/grid_layout.hpp>
|
#include <psemek/ui/grid_layout.hpp>
|
||||||
|
#include <psemek/ui/button.hpp>
|
||||||
|
|
||||||
#include <psemek/async/event_loop.hpp>
|
#include <psemek/async/event_loop.hpp>
|
||||||
|
|
||||||
|
|
@ -38,42 +39,28 @@ struct ui_example
|
||||||
: app("UI example", 1)
|
: app("UI example", 1)
|
||||||
, ui_controller(&loop)
|
, ui_controller(&loop)
|
||||||
{
|
{
|
||||||
auto style = std::make_shared<ui::style>();
|
auto style = std::make_shared<ui::style>(ui::default_style());
|
||||||
style->font = ui::make_default_9x12_font();
|
style->font = ui::make_default_9x12_font();
|
||||||
style->text_scale = 2;
|
style->text_scale = 2;
|
||||||
|
|
||||||
auto screen = element_factory.make_screen();
|
auto screen = element_factory.make_screen();
|
||||||
screen->set_style(style);
|
screen->set_style(style);
|
||||||
|
|
||||||
auto grid = element_factory.make_grid_layout();
|
std::shared_ptr<ui::button> button;
|
||||||
grid->set_size(1, 1);
|
{
|
||||||
auto button = element_factory.make_button("0,0");
|
gfx::pixmap_rgba pm({32, 32});
|
||||||
grid->set(0, 0, button);
|
for (int x = 0; x < pm.width(); ++x)
|
||||||
button->on_click(util::recursive([this, grid](auto && self) -> void {
|
|
||||||
while (true)
|
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < grid->row_count(); ++i)
|
for (int y = 0; y < pm.height(); ++y)
|
||||||
{
|
{
|
||||||
for (std::size_t j = 0; j < grid->column_count(); ++j)
|
pm(x, y) = {(x * 255) / pm.width(), (y * 255) / pm.height(), 0, 255};
|
||||||
{
|
|
||||||
if (!grid->get(i, j))
|
|
||||||
{
|
|
||||||
auto button = element_factory.make_button(util::to_string(i, ",", j));
|
|
||||||
grid->set(i, j, button);
|
|
||||||
button->on_click(self);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grid->row_count() <= grid->column_count())
|
|
||||||
grid->set_row_count(grid->row_count() + 1);
|
|
||||||
else
|
|
||||||
grid->set_column_count(grid->column_count() + 1);
|
|
||||||
}
|
}
|
||||||
}));
|
auto tex = std::make_shared<gfx::texture_2d>(gfx::texture_2d::from_pixmap(pm));
|
||||||
|
tex->nearest_filter();
|
||||||
screen->add_child(grid, ui::screen::x_policy::center, ui::screen::y_policy::center);
|
button = element_factory.make_button(tex);
|
||||||
|
}
|
||||||
|
screen->add_child(button, ui::screen::x_policy::center, ui::screen::y_policy::center);
|
||||||
|
|
||||||
ui_controller.set_root(std::move(screen));
|
ui_controller.set_root(std::move(screen));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,34 @@
|
||||||
#include <psemek/ui/font.hpp>
|
#include <psemek/ui/font.hpp>
|
||||||
#include <psemek/gfx/color.hpp>
|
#include <psemek/gfx/color.hpp>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace psemek::ui
|
namespace psemek::ui
|
||||||
{
|
{
|
||||||
|
|
||||||
struct style
|
struct style
|
||||||
{
|
{
|
||||||
gfx::color_rgba bg_color{95, 95, 95, 255};
|
std::optional<gfx::color_rgba> bg_color;
|
||||||
gfx::color_rgba fg_color{127, 127, 127, 255};
|
std::optional<gfx::color_rgba> fg_color;
|
||||||
gfx::color_rgba highlight_color{159, 159, 159, 255};
|
std::optional<gfx::color_rgba> highlight_color;
|
||||||
gfx::color_rgba action_color{63, 63, 63, 255};
|
std::optional<gfx::color_rgba> action_color;
|
||||||
|
|
||||||
gfx::color_rgba border_color{255, 255, 255, 255};
|
std::optional<gfx::color_rgba> border_color;
|
||||||
int border_width = 3;
|
std::optional<int> border_width;
|
||||||
|
|
||||||
geom::vector<int, 2> shadow_offset{1, 1};
|
std::optional<geom::vector<int, 2>> shadow_offset;
|
||||||
gfx::color_rgba shadow_color{0, 0, 0, 255};
|
std::optional<gfx::color_rgba> shadow_color;
|
||||||
|
|
||||||
int inner_margin = 5;
|
std::optional<int> inner_margin;
|
||||||
int outer_margin = 10;
|
std::optional<int> outer_margin;
|
||||||
|
|
||||||
|
std::optional<gfx::color_rgba> text_color;
|
||||||
|
std::optional<int> text_scale;
|
||||||
|
std::optional<geom::vector<int, 2>> text_shadow_offset;
|
||||||
|
|
||||||
gfx::color_rgba text_color{255, 255, 255, 255};
|
|
||||||
int text_scale = 1;
|
|
||||||
geom::vector<int, 2> text_shadow_offset{1, 1};
|
|
||||||
std::shared_ptr<struct font> font;
|
std::shared_ptr<struct font> font;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
style default_style();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace psemek::ui
|
||||||
shape_.box = bbox;
|
shape_.box = bbox;
|
||||||
auto s = style();
|
auto s = style();
|
||||||
element * c = label() ? (element *)label() : icon();
|
element * c = label() ? (element *)label() : icon();
|
||||||
if (s && c) c->reshape(geom::shrink(bbox, 1.f * (s->border_width + s->inner_margin)));
|
if (s && c) c->reshape(geom::shrink(bbox, 1.f * (*s->border_width + *s->inner_margin)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_state_changed() override
|
void on_state_changed() override
|
||||||
|
|
@ -67,17 +67,17 @@ namespace psemek::ui
|
||||||
if (!s) return;
|
if (!s) return;
|
||||||
|
|
||||||
if (s->shadow_offset != geom::vector{0, 0})
|
if (s->shadow_offset != geom::vector{0, 0})
|
||||||
p.draw_rect(shape_.box + geom::cast<float>(s->shadow_offset), s->shadow_color);
|
p.draw_rect(shape_.box + geom::cast<float>(*s->shadow_offset), *s->shadow_color);
|
||||||
|
|
||||||
if (s->border_width > 0)
|
if (s->border_width > 0)
|
||||||
p.draw_rect(shape_.box, s->border_color);
|
p.draw_rect(shape_.box, *s->border_color);
|
||||||
|
|
||||||
gfx::color_rgba color = s->fg_color;
|
gfx::color_rgba color = *s->fg_color;
|
||||||
if (state() == state_t::mouseover)
|
if (state() == state_t::mouseover)
|
||||||
color = s->highlight_color;
|
color = *s->highlight_color;
|
||||||
else if (state() == state_t::mousedown)
|
else if (state() == state_t::mousedown)
|
||||||
color = s->action_color;
|
color = *s->action_color;
|
||||||
p.draw_rect(geom::shrink(shape_.box, 1.f * s->border_width), color);
|
p.draw_rect(geom::shrink(shape_.box, 1.f * (*s->border_width)), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
geom::box<float, 2> size_constraints() const override
|
geom::box<float, 2> size_constraints() const override
|
||||||
|
|
@ -92,7 +92,7 @@ namespace psemek::ui
|
||||||
|
|
||||||
if (auto st = style())
|
if (auto st = style())
|
||||||
{
|
{
|
||||||
float extra = 2.f * (st->border_width + st->inner_margin);
|
float extra = 2.f * (*st->border_width + *st->inner_margin);
|
||||||
sc[0] += extra;
|
sc[0] += extra;
|
||||||
sc[1] += extra;
|
sc[1] += extra;
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +116,7 @@ namespace psemek::ui
|
||||||
auto st = style();
|
auto st = style();
|
||||||
if (!st) return;
|
if (!st) return;
|
||||||
for (auto c : children())
|
for (auto c : children())
|
||||||
if (c) c->reshape(geom::shrink(bbox, 1.f * (st->border_width + st->outer_margin)));
|
if (c) c->reshape(geom::shrink(bbox, 1.f * (*st->border_width + *st->outer_margin)));
|
||||||
}
|
}
|
||||||
|
|
||||||
geom::box<float, 2> size_constraints() const override
|
geom::box<float, 2> size_constraints() const override
|
||||||
|
|
@ -130,7 +130,7 @@ namespace psemek::ui
|
||||||
auto st = style();
|
auto st = style();
|
||||||
if (st)
|
if (st)
|
||||||
{
|
{
|
||||||
float extra = 2.f * (st->border_width + st->outer_margin);
|
float extra = 2.f * (*st->border_width + *st->outer_margin);
|
||||||
r[0] += extra;
|
r[0] += extra;
|
||||||
r[1] += extra;
|
r[1] += extra;
|
||||||
}
|
}
|
||||||
|
|
@ -158,11 +158,11 @@ namespace psemek::ui
|
||||||
if (!st) return;
|
if (!st) return;
|
||||||
|
|
||||||
if (st->shadow_offset != geom::vector{0, 0})
|
if (st->shadow_offset != geom::vector{0, 0})
|
||||||
p.draw_rect(shape_.box + geom::cast<float>(st->shadow_offset), st->shadow_color);
|
p.draw_rect(shape_.box + geom::cast<float>(*st->shadow_offset), *st->shadow_color);
|
||||||
|
|
||||||
if (st->border_width > 0)
|
if (st->border_width > 0)
|
||||||
p.draw_rect(shape_.box, st->border_color);
|
p.draw_rect(shape_.box, *st->border_color);
|
||||||
p.draw_rect(geom::shrink(shape_.box, 1.f * st->border_width), st->bg_color);
|
p.draw_rect(geom::shrink(shape_.box, 1.f * (*st->border_width)), *st->bg_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -155,8 +155,8 @@ namespace psemek::ui
|
||||||
result[0].max += column_size[i].max;
|
result[0].max += column_size[i].max;
|
||||||
}
|
}
|
||||||
|
|
||||||
result[1] += (row_count() + 1) * st->outer_margin;
|
result[1] += (row_count() + 1) * (*st->outer_margin);
|
||||||
result[0] += (column_count() + 1) * st->outer_margin;
|
result[0] += (column_count() + 1) * (*st->outer_margin);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ namespace psemek::ui
|
||||||
auto st = style();
|
auto st = style();
|
||||||
if (!st) return;
|
if (!st) return;
|
||||||
|
|
||||||
float const margin = st->outer_margin;
|
float const margin = *st->outer_margin;
|
||||||
|
|
||||||
float const available_width = std::max(0.f, bbox[0].length() - margin * (1 + column_count()));
|
float const available_width = std::max(0.f, bbox[0].length() - margin * (1 + column_count()));
|
||||||
float const available_height = std::max(0.f, bbox[1].length() - margin * (1 + row_count()));
|
float const available_height = std::max(0.f, bbox[1].length() - margin * (1 + row_count()));
|
||||||
|
|
|
||||||
|
|
@ -63,10 +63,10 @@ namespace psemek::ui
|
||||||
|
|
||||||
if (st->text_shadow_offset != geom::vector{0, 0})
|
if (st->text_shadow_offset != geom::vector{0, 0})
|
||||||
for (auto & g : cached_state_->glyphs)
|
for (auto & g : cached_state_->glyphs)
|
||||||
p.draw_glyph(*(cached_state_->font), g.character, g.position + geom::cast<float>(st->text_shadow_offset), st->shadow_color);
|
p.draw_glyph(*(cached_state_->font), g.character, g.position + geom::cast<float>(*st->text_shadow_offset), *st->shadow_color);
|
||||||
|
|
||||||
for (auto & g : cached_state_->glyphs)
|
for (auto & g : cached_state_->glyphs)
|
||||||
p.draw_glyph(*(cached_state_->font), g.character, g.position, st->text_color);
|
p.draw_glyph(*(cached_state_->font), g.character, g.position, *st->text_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void label::on_state_changed()
|
void label::on_state_changed()
|
||||||
|
|
@ -98,7 +98,7 @@ namespace psemek::ui
|
||||||
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;
|
||||||
auto glyphs = st->font->shape(text_, opts);
|
auto glyphs = st->font->shape(text_, opts);
|
||||||
|
|
||||||
geom::box<float, 2> raw_bbox;
|
geom::box<float, 2> raw_bbox;
|
||||||
|
|
@ -114,7 +114,7 @@ namespace psemek::ui
|
||||||
break;
|
break;
|
||||||
case multiline_mode::minimize_lines:
|
case multiline_mode::minimize_lines:
|
||||||
max_lines = std::isfinite(bbox[1].length())
|
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::max<std::size_t>(1, std::floor(bbox[1].length() / st->font->size()[1] / (*st->text_scale)))
|
||||||
: std::numeric_limits<std::size_t>::max();
|
: std::numeric_limits<std::size_t>::max();
|
||||||
break;
|
break;
|
||||||
case multiline_mode::minimize_area:
|
case multiline_mode::minimize_area:
|
||||||
|
|
@ -226,13 +226,13 @@ namespace psemek::ui
|
||||||
switch (valign_)
|
switch (valign_)
|
||||||
{
|
{
|
||||||
case valignment::top:
|
case valignment::top:
|
||||||
offset[1] = bbox[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] = bbox[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] = bbox[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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +242,7 @@ namespace psemek::ui
|
||||||
|
|
||||||
state.glyphs = std::move(glyphs);
|
state.glyphs = std::move(glyphs);
|
||||||
state.size[0] = max_line_size;
|
state.size[0] = max_line_size;
|
||||||
state.size[1] = lines.size() * st->text_scale * st->font->size()[1];
|
state.size[1] = lines.size() * (*st->text_scale) * st->font->size()[1];
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
libs/ui/source/style.cpp
Normal file
29
libs/ui/source/style.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <psemek/ui/style.hpp>
|
||||||
|
|
||||||
|
namespace psemek::ui
|
||||||
|
{
|
||||||
|
|
||||||
|
style default_style()
|
||||||
|
{
|
||||||
|
style s;
|
||||||
|
s.bg_color = {95, 95, 95, 255};
|
||||||
|
s.fg_color = {127, 127, 127, 255};
|
||||||
|
s.highlight_color = {159, 159, 159, 255};
|
||||||
|
s.action_color = {63, 63, 63, 255};
|
||||||
|
|
||||||
|
s.border_color = {255, 255, 255, 255};
|
||||||
|
s.border_width = 3;
|
||||||
|
|
||||||
|
s.shadow_offset = {1, 1};
|
||||||
|
s.shadow_color = {0, 0, 0, 255};
|
||||||
|
|
||||||
|
s.inner_margin = 5;
|
||||||
|
s.outer_margin = 10;
|
||||||
|
|
||||||
|
s.text_color = {255, 255, 255, 255};
|
||||||
|
s.text_scale = 1;
|
||||||
|
s.text_shadow_offset = {1, 1};
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue