Euphoria
button.cc
Go to the documentation of this file.
1 #include "gui/button.h"
2 #include "gui/uistate.h"
3 
5 #include "render/spriterender.h"
6 #include "render/font.h"
7 
8 #include "gui/visitor.h"
9 #include "gui/skin.h"
10 
11 
12 namespace eu::gui
13 {
15  : Widget(state)
16  , last_state(nullptr)
17  , skin(nullptr)
18  , scale(1.0f)
19  , image_color(Rgb(1.0f))
20  , text_color(Rgb(1.0f))
21  , position_displacement(zero2f)
22  {
23  }
24 
25 
26  Button::~Button() = default;
27 
28 
29  void
30  Button::update(float dt)
31  {
32  if(get_background_rect().contains_exclusive(get_state().mouse))
33  {
34  get_state_ptr()->set_hot(this);
35  if(get_state().is_mouse_down())
36  {
37  get_state_ptr()->set_active(this);
38  }
39  }
40 
41  const bool mouse_down = get_state().is_mouse_down();
42  const bool is_clicked = mouse_down == false && is_hot() && is_active();
43  if(is_clicked)
44  {
45  on_clicked();
46  }
47 
48  if(skin != nullptr)
49  {
50  auto* cold_state = &skin->button_idle;
51  auto* hot_state = is_active()
53  : &skin->button_hot
54  ;
55  auto* state = is_hot() ? hot_state : cold_state;
56 
57  if(last_state != state)
58  {
59  last_state = state;
60  scale.set
61  (
62  state->interpolation_size.type,
63  state->scale,
64  state->interpolation_size.time
65  );
66  image_color.set
67  (
68  state->interpolation_color.type,
69  state->image_color,
70  state->interpolation_color.time
71  );
72  text_color.set
73  (
74  state->interpolation_color.type,
75  state->text_color,
76  state->interpolation_color.time
77  );
79  (
80  state->interpolation_position.type,
81  vec2f(state->dx, state->dy),
82  state->interpolation_position.time
83  );
84  }
85 
86  scale.update(dt);
87  image_color.update(dt);
88  text_color.update(dt);
89  position_displacement.update(dt);
91  }
92  }
93 
94 
95  size2f
97  {
98  auto size = size2f::create_from_width_height(0, 0);
99  if(sprite != nullptr)
100  {
101  const auto ms = sprite->get_minimum_size();
102  size.width = (size.width + ms.width);
103  size.height = (size.height + ms.height);
104  }
105 
106  if(text.has_text())
107  {
108  const auto extents = text.get_text().get_extents();
109  const auto ms = size2f::create_from_width_height
110  (
111  extents.get_width(),
112  extents.get_height()
113  );
114  size.width = size.width + ms.width;
115  size.height = size.height + ms.height;
116  }
117 
118  return size;
119  }
120 
121 
122  void
124  {
125  if(skin != nullptr)
126  {
127  if(sprite != nullptr)
128  {
129  const auto background_rect = get_background_rect();
130 
131  ASSERTX(scale.value > 0, scale.value);
132  const auto scaled = background_rect.get_scaled_around_center_copy
133  (
134  scale.value
135  );
136  ASSERTX(scaled.get_width() > 0, scaled.get_width());
137  ASSERTX(scaled.get_height() > 0, scaled.get_height());
138  renderer->draw_ninepatch
139  (
140  *sprite,
141  scaled.translate_copy(position_displacement.value),
142  image_color.value
143  );
144  }
145 
146  if(text.has_text())
147  {
148  const auto ex = text.get_text().get_extents();
149  // todo(Gustav): render text at client Rect center
150 
151  const auto base = ex.center_inside_other(get_client_rect());
152  const auto base_pos = base.get_bottom_left();
153  const auto p = base_pos + position_displacement.value;
154  text.get_text().draw(renderer, p, text_color.value);
155  }
156  }
157  }
158 
159 
160  void
162  {
163  visitor->visit(this);
164  }
165 
166 
167  void
169  {
170  }
171 
172 
173  void
175  {
176  skin = new_skin;
177  if(skin != nullptr)
178  {
180  }
181  }
182 }
183 
ParserBase * base
Definition: argparse.cc:887
#define ASSERTX(x,...)
Definition: assert.h:48
constexpr vec2f zero2f
Definition: vec2.h:68
Definition: rgb.h:62
void update(float dt, F transform_function)
Definition: tweenable.h:62
Self & set(const T &new_value)
Definition: tweenable.h:38
TextData text
Definition: button.h:29
Button(gui::State *state)
Definition: button.cc:14
virtual void on_clicked()=0
void render(render::SpriteRenderer *renderer) const override
Definition: button.cc:123
void visit(Visitor *visitor) override
Definition: button.cc:161
ButtonState * last_state
Definition: button.h:27
std::shared_ptr< render::ScalableSprite > sprite
Definition: button.h:28
core::Tweenable< vec2f > position_displacement
Definition: button.h:35
void update(float dt) override
Definition: button.cc:30
size2f calc_minimum_size() const override
Definition: button.cc:96
void set_skin(Skin *new_skin)
Definition: button.cc:174
~Button() override
core::Tweenable< Rgb > image_color
Definition: button.h:33
Skin * skin
Definition: button.h:30
core::Tweenable< Rgb > text_color
Definition: button.h:34
core::Tweenable< float > scale
Definition: button.h:32
void on_size_changed() override
Definition: button.cc:168
ButtonState button_idle
Definition: skin.h:57
ButtonState button_active_hot
Definition: skin.h:59
float text_size
Definition: skin.h:53
ButtonState button_hot
Definition: skin.h:58
void set_hot(Widget *w)
void set_active(Widget *w)
bool is_mouse_down() const
bool has_text() const
Definition: textdata.cc:47
const render::DrawableText & get_text() const
Definition: textdata.cc:54
void set_size(float size)
Definition: textdata.cc:70
virtual void visit(Button *button)=0
Rectf get_client_rect() const
Definition: widget.cc:42
const gui::State & get_state() const
Definition: widget.cc:95
bool is_hot() const
Definition: widget.cc:29
Rectf get_background_rect() const
Definition: widget.cc:49
gui::State * get_state_ptr() const
Definition: widget.cc:102
bool is_active() const
Definition: widget.cc:22
Rectf get_extents() const
Definition: font.cc:641
void draw(SpriteRenderer *renderer, const vec2f &p, const Rgb &base_hi_color) const
Definition: font.cc:587
void draw_ninepatch(const ScalableSprite &ninepatch, const Rectf &rect, const Rgba &tint)
static size2f create_from_width_height(float w, float h)
Definition: size2.cc:15
Definition: vec2.h:33
ParserState state
Definition: ui_text.cc:134