somewhat working code

This commit is contained in:
Andrea Blankenstijn 2021-07-11 17:06:18 +02:00
parent dcbeeea882
commit 938bb8396c
16 changed files with 138 additions and 142 deletions

View file

@ -2,7 +2,7 @@
#include <SDL2/SDL_ttf.h>
#include <basic_widgets/button.hpp>
#include <basic_widgets/caption.hpp>
#include <basic_widgets/horizontal_layout.hpp>
#include <basic_widgets/utils/font.hpp>
#include <basic_widgets/vertical_layout.hpp>
@ -37,11 +37,8 @@ int main()
auto column = new Vertical_Layout();
for (int j = 0; j < 3; j++)
{
auto widget = new Button();
widget->text("hello");
widget->click_handler = [i, j](const SDL_MouseButtonEvent&) {
std::cerr << "click@" << j << ":" << i << std::endl;
};
auto widget = new Caption();
widget->text("hi");
widget->font(font);
column->add_widget(widget);
std::cerr << " " << i << "@" << widget;

View file

@ -40,7 +40,6 @@ int main()
widget->font(font);
widget->value_range(-2.5, 2.5);
column->add_widget(widget);
std::cerr << " " << i << "@" << widget;
}
layout->add_widget(column);
}

View file

@ -33,23 +33,27 @@ namespace bwidgets::abstract
const int _border_width {3};
SDL_Rect _input_area {};
widget::Caption _input_caption;
SDL_Rect _input_caption_area {};
T _value {};
Input(Widget* parent=nullptr)
: Widget(parent)
{
MouseHandler::_focus_area = &_input_area;
MouseHandler::_button_area = &_input_area;
MouseHandler::_click_area = &_input_area;
_input_caption.text(value_to_string(_value));
}
virtual void _handle_focus_change()
{
if (MouseHandler::_has_focus)
{
KeyboardHandler::_has_focus = true;
SDL_StartTextInput();
}
else
{
KeyboardHandler::_has_focus = false;
value(value_from_string(input_text()));
input_text(value_to_string(_value));
SDL_StopTextInput();
}
@ -58,6 +62,7 @@ namespace bwidgets::abstract
virtual void _handle_font_change()
{
_input_caption.font(_font);
_update_widget_area();
}
virtual void _handle_key(const SDL_KeyboardEvent& key)
@ -73,13 +78,13 @@ namespace bwidgets::abstract
{
txt.pop_back();
input_text(txt);
value(value_from_string(txt));
}
break;
}
case SDLK_RETURN:
case SDLK_RETURN2: // what is return2 btw?
case SDLK_KP_ENTER:
value(value_from_string(input_text()));
input_text(value_to_string(_value));
break;
}
@ -92,17 +97,17 @@ namespace bwidgets::abstract
{
std::string new_txt_value = input_text() + input.text;
input_text(new_txt_value);
value(value_from_string(new_txt_value));
}
}
virtual void _update_widget_area()
{
_widget_area = {
_viewport.x,
utils::math::center_rect(_viewport.h, _input_caption.height()),
0,
utils::math::center_rect(_viewport.h,
_input_caption.text_size().h + 2 * _border_width),
_viewport.w,
_input_caption.height()
_input_caption.text_size().h + 2 * _border_width
};
_input_area = {
_widget_area.x + _border_width,
@ -110,17 +115,13 @@ namespace bwidgets::abstract
_widget_area.w - 2 * _border_width,
_widget_area.h - 2 * _border_width
};
_input_caption.viewport(
utils::math::rect_offset(_input_area, _viewport)
);
}
public:
SDL_Color color_border {160, 160, 160, SDL_ALPHA_OPAQUE};
SDL_Color color_bg {200, 200, 200, SDL_ALPHA_OPAQUE};
int float_precision {2};
SDL_Color focused_bg_color {255, 255, 255, SDL_ALPHA_OPAQUE};
SDL_Color color_bg_focused {255, 255, 255, SDL_ALPHA_OPAQUE};
virtual void color_fg(const SDL_Color& c)
{
@ -153,7 +154,7 @@ namespace bwidgets::abstract
SDL_RenderSetViewport(r, &_viewport);
for (int i = 3; i > 0; i--)
for (int i = _border_width; i > 0; i--)
{
SDL_SetRenderDrawColor(
r,
@ -163,20 +164,18 @@ namespace bwidgets::abstract
color_border.a
);
SDL_Rect border_area = {
_widget_area.x + 3 - i,
_widget_area.y + 3 - i,
_widget_area.w - 2 * (3 - i),
_widget_area.h - 2 * (3 - i)
_input_area.x - i,
_input_area.y - i,
_input_area.w + 2 * i,
_input_area.h + 2 * i
};
SDL_RenderDrawRect(r, &border_area);
}
SDL_Color* c = &color_bg;
if (MouseHandler::_has_focus)
c = &focused_bg_color;
SDL_SetRenderDrawColor(r, c->r, c->g, c->b, c->a);
SDL_RenderFillRect(r, &_input_area);
if (MouseHandler::_is_hovered || MouseHandler::_has_focus)
_input_caption.color_bg = color_bg_focused;
else
_input_caption.color_bg = color_bg;
_input_caption.render(r);
}
@ -189,7 +188,6 @@ namespace bwidgets::abstract
void value(T new_value)
{
_value = new_value;
_input_caption.text(value_to_string(_value));
_update_widget_area();
}
@ -245,6 +243,15 @@ namespace bwidgets::abstract
return s;
}
virtual void viewport(SDL_Rect vp)
{
Widget::viewport(vp);
_input_caption.viewport(
utils::math::rect_offset(_input_area, _viewport)
);
}
};
}

View file

@ -10,7 +10,7 @@ namespace bwidgets::abstract
class Layout : public abstract::Widget
{
protected:
int _interspace = 16;
int _interspace = 8;
std::vector<Widget*> _widgets;
virtual void _update_layout() = 0;

View file

@ -14,9 +14,9 @@ namespace bwidgets::abstract
class MouseHandler : public FocusHandler
{
protected:
const SDL_Rect* _button_area = nullptr;
bool _is_hovered = false;
bool _is_pushed = false;
const SDL_Rect* _click_area = nullptr;
bool _is_hovered = false;
bool _is_pushed = false;
virtual void _handle_focus_change();
virtual void _handle_mouse_button(const SDL_MouseButtonEvent&,
@ -25,7 +25,7 @@ namespace bwidgets::abstract
const SDL_Rect&);
public:
std::function<void (const SDL_MouseButtonEvent&)> click_handler;
std::function<void (const SDL_MouseButtonEvent&)> click_handler = nullptr;
virtual void handle_mouse(const SDL_MouseButtonEvent&,
const SDL_Rect&);

View file

@ -28,6 +28,8 @@ namespace bwidgets::widget
SDL_Color color_bg {150, 150, 150, SDL_ALPHA_OPAQUE};
SDL_Color color_bg_hover {175, 175, 175, SDL_ALPHA_OPAQUE};
Button(Widget* parent=nullptr);
int height() const;
void render(SDL_Renderer*);
const std::string& text() const;

View file

@ -21,25 +21,24 @@ namespace bwidgets::widget
};
private:
Alignment _alignment {Alignment::RIGHT};
SDL_Color _color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
SDL_Color _color_fg {0, 0, 0, SDL_ALPHA_OPAQUE};
std::string _text;
SDL_Surface* _rendered_text {nullptr};
SDL_Texture* _text_texture {nullptr};
SDL_Renderer* _renderer {nullptr};
SDL_Surface* _text_surface {nullptr};
SDL_Texture* _text_texture {nullptr};
SDL_Renderer* _renderer {nullptr};
void _handle_font_change();
void _render_text();
void _update_widget_area();
public:
SDL_Color color_bg {0, 0, 0, SDL_ALPHA_TRANSPARENT};
Alignment alignment {Alignment::LEFT};
SDL_Color color_bg {0, 0, 0, SDL_ALPHA_TRANSPARENT};
~Caption();
void align(Alignment);
void color_fg(const SDL_Color&);
void render(SDL_Renderer*);
abstract::Widget::Size size() const;
abstract::Widget::Size text_size() const;
const std::string& text() const;
void text(const std::string&);

View file

@ -25,36 +25,31 @@ namespace bwidgets::widget
SDL_Rect _decrement_button_area;
std::pair<T, T> _value_range {
std::numeric_limits<T>::lowest(),
std::numeric_limits<T>::max()
std::numeric_limits<T>::max()
};
void handle_event(const SDL_Event& ev)
void _handle_font_change()
{
abstract::Widget::handle_event(ev);
_increment_button.handle_event(ev);
_decrement_button.handle_event(ev);
_decrement_button.font(abstract::FontHandler::_font);
_increment_button.font(abstract::FontHandler::_font);
abstract::Input<T>::_handle_font_change();
}
void _update_drawing_areas()
void _update_widget_area()
{
abstract::Input<T>::_update_widget_area();
const int widest_button =
_increment_button.width() > _decrement_button.width()
? _increment_button.width()
: _decrement_button.width();
const int heighest_button =
_increment_button.height() > _decrement_button.height()
? _increment_button.height()
: _decrement_button.height();
const int button_area_width = 2 * widest_button;
const int spacing = utils::math::center_rect(button_area_width, widest_button);
const int field_width = abstract::Widget::_viewport.w - 2 * button_area_width;
const int field_height = heighest_button;
abstract::Input<T>::_input_field_area = {
(int)button_area_width,
utils::math::center_rect(abstract::Widget::_viewport.h, field_height),
field_width,
field_height
};
abstract::Input<T>::_input_area.x =
abstract::Widget::_widget_area.x + button_area_width;
abstract::Input<T>::_input_area.w = field_width;
_increment_button_area = {
spacing,
@ -69,16 +64,6 @@ namespace bwidgets::widget
_decrement_button.width(),
_decrement_button.height()
};
abstract::Widget::_widget_area = {
button_area_width,
utils::math::center_rect(abstract::Widget::_viewport.h, heighest_button),
abstract::Widget::_viewport.w
- 2 * button_area_width,
heighest_button
};
abstract::Input<T>::_update_drawing_areas();
}
public:
@ -89,6 +74,8 @@ namespace bwidgets::widget
_increment_button(), // FIXME: parenthood
_decrement_button()
{
abstract::Input<T>::_input_caption.alignment =
widget::Caption::Alignment::RIGHT;
_increment_button.text("+");
_increment_button.click_handler = [this](const SDL_MouseButtonEvent&) {
T new_value = this->value() + button_step;
@ -109,10 +96,11 @@ namespace bwidgets::widget
};
}
void handle_font_chage()
void handle_event(const SDL_Event& ev)
{
_decrement_button.font(abstract::FontHandler::_font);
_increment_button.font(abstract::FontHandler::_font);
abstract::Widget::handle_event(ev);
_increment_button.handle_event(ev);
_decrement_button.handle_event(ev);
}
bool is_valid_input(const std::string input) const
@ -173,18 +161,12 @@ namespace bwidgets::widget
{
abstract::Input<T>::viewport(vp);
_increment_button.viewport({
abstract::Widget::_viewport.x + _increment_button_area.x,
abstract::Widget::_viewport.y + _increment_button_area.y,
_increment_button_area.w,
_increment_button_area.h
});
_decrement_button.viewport({
abstract::Widget::_viewport.x + _decrement_button_area.x,
abstract::Widget::_viewport.y + _decrement_button_area.y,
_decrement_button_area.w,
_decrement_button_area.h
});
_increment_button.viewport(utils::math::rect_offset(
_increment_button_area, abstract::Widget::_viewport
));
_decrement_button.viewport(utils::math::rect_offset(
_decrement_button_area, abstract::Widget::_viewport
));
}
};
}

View file

@ -39,6 +39,12 @@ executable('button_demo',
link_with : libbasic_widgets,
install : false)
executable('caption_demo',
'examples/caption_example.cpp',
include_directories : pub_api,
link_with : libbasic_widgets,
install : false)
executable('input_demo',
'examples/input_example.cpp',
include_directories : pub_api,

View file

@ -2,13 +2,21 @@
#include <basic_widgets/button.hpp>
#include <basic_widgets/utils/math.hpp>
#include <iostream>
using namespace bwidgets;
using namespace bwidgets::utils;
widget::Button::Button(Widget* parent)
: abstract::Widget(parent)
{
_focus_area = _click_area = &_widget_area;
_caption.alignment = Caption::Alignment::CENTER;
}
int widget::Button::height() const
{
return _caption.height() * _caption_height_multiplicator
return _caption.text_size().h * _caption_height_multiplicator
+ 2 * border_width;
}
@ -18,6 +26,7 @@ void widget::Button::render(SDL_Renderer* r)
SDL_RenderSetViewport(r, &_viewport);
// TODO: smoothstep it
auto color_shade = [](int base, int step, int total_steps) -> int {
int steps_to_max = 255 - base;
return base + step * steps_to_max / total_steps;
@ -89,7 +98,7 @@ void widget::Button::viewport(SDL_Rect vp)
int widget::Button::width() const
{
return _caption.width() * _caption_height_multiplicator
return _caption.text_size().w * _caption_height_multiplicator
+ 2 * border_width;
}

View file

@ -3,13 +3,14 @@
#include <basic_widgets/caption.hpp>
#include <basic_widgets/utils/math.hpp>
#include <iostream>
using namespace bwidgets;
using namespace bwidgets::utils;
widget::Caption::~Caption()
{
SDL_FreeSurface(_rendered_text);
SDL_FreeSurface(_text_surface);
SDL_DestroyTexture(_text_texture);
}
@ -30,20 +31,48 @@ void widget::Caption::render(SDL_Renderer* r)
_renderer = r;
if (_font == nullptr)
SDL_RenderSetViewport(r, &_viewport);
SDL_SetRenderDrawColor(r, color_bg.r, color_bg.g, color_bg.b, color_bg.a);
SDL_RenderFillRect(r, &_widget_area);
if (_text_surface== nullptr)
return;
SDL_RenderSetViewport(r, &_viewport);
if (_text_texture == nullptr || _renderer != r)
{
_renderer = r;
_text_texture = SDL_CreateTextureFromSurface(r, _rendered_text);
_text_texture = SDL_CreateTextureFromSurface(r, _text_surface);
}
abstract::Widget::Size size_dst {
(int)((float)_text_surface->w / _text_surface->h * _viewport.h),
_viewport.h
};
SDL_Rect texture_dst {
0,
utils::math::center_rect(_viewport.h, _text_surface->h),
size_dst.w,
size_dst.h
};
switch (alignment)
{
case Alignment::CENTER:
texture_dst.x = utils::math::center_rect(_viewport.w, texture_dst.w);
break;
case Alignment::LEFT:
break;
case Alignment::RIGHT:
texture_dst.x = _viewport.w - texture_dst.w - 3;
break;
}
SDL_RenderCopy(
r,
_text_texture,
NULL,
&_widget_area
&texture_dst
);
}
@ -52,12 +81,14 @@ void widget::Caption::_render_text()
if (_font == nullptr)
return;
SDL_FreeSurface(_rendered_text);
_rendered_text = TTF_RenderUTF8_Blended(
SDL_FreeSurface(_text_surface);
_text_surface = TTF_RenderUTF8_Blended(
_font,
_text.c_str(),
_color_fg
);
SDL_DestroyTexture(_text_texture);
_text_texture = nullptr;
_update_widget_area();
}
@ -77,46 +108,10 @@ void widget::Caption::text(const std::string& t)
abstract::Widget::Size widget::Caption::text_size() const
{
if (_font == nullptr)
return {0, 0};
return {-1, -1};
abstract::Widget::Size size;
TTF_SizeUTF8(_font, _text.c_str(), &size.w, &size.h);
return size;
}
void widget::Caption::_update_widget_area()
{
Widget::_update_widget_area();
if (_font == nullptr)
return;
auto txt_size = text_size();
SDL_Rect resized_txt = {};
if (_widget_area.w > _widget_area.h)
{
resized_txt.h = _widget_area.h;
resized_txt.w = resized_txt.h / (txt_size.h * txt_size.w);
switch (_alignment)
{
case Alignment::CENTER:
_widget_area.x = math::center_rect(_widget_area.w, resized_txt.w);
break;
case Alignment::LEFT:
break;
case Alignment::RIGHT:
_widget_area.x = _widget_area.w - resized_txt.w;
}
}
else
{
resized_txt.w = _widget_area.w;
if (txt_size.w > 0)
resized_txt.h = resized_txt.w / (txt_size.w * txt_size.h);
else
resized_txt.h = txt_size.w;
_widget_area.y = math::center_rect(_widget_area.h, resized_txt.h);
}
}

View file

@ -4,13 +4,13 @@ using namespace bwidgets;
void widget::Horizontal_Layout::_update_layout()
{
int widget_size = _viewport.w / _widgets.size();
int widget_size = (_viewport.w - _widgets.size() * _interspace) / _widgets.size();
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++)
{
_widgets.at(i)->viewport({
_viewport.x + (int)(_interspace / 2.0 +
i * (widget_size + _interspace / 2.0)),
_viewport.x + (int)(_interspace +
i * (widget_size + _interspace)),
_viewport.y,
widget_size - _interspace,
_viewport.h

View file

@ -25,9 +25,6 @@ void abstract::Layout::render(SDL_Renderer* r)
{
SDL_RenderSetViewport(r, &_viewport);
SDL_SetRenderDrawColor(r, 255, 0, 0, SDL_ALPHA_OPAQUE);
SDL_RenderDrawRect(r, NULL);
for (Widget* widget_ptr : _widgets)
widget_ptr->render(r);
}

View file

@ -10,11 +10,11 @@ using namespace bwidgets::utils;
void abstract::MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev,
const SDL_Rect& orig)
{
if (_button_area == nullptr)
if (_click_area == nullptr)
return;
SDL_Point p {ev.x, ev.y};
SDL_Rect vp = math::rect_offset(*_button_area, orig);
SDL_Rect vp = math::rect_offset(*_click_area, orig);
if (ev.type == SDL_MOUSEBUTTONDOWN)
{
if (SDL_PointInRect(&p, &vp))
@ -32,6 +32,9 @@ void abstract::MouseHandler::handle_mouse(const SDL_MouseButtonEvent& ev,
if (SDL_PointInRect(&p, &vp))
{
focus(true);
if (click_handler != nullptr)
click_handler(ev);
}
_is_pushed = false;
_handle_mouse_button(ev, vp);
@ -46,7 +49,7 @@ void abstract::MouseHandler::handle_mouse(const SDL_MouseMotionEvent& ev,
return;
SDL_Point p {ev.x, ev.y};
SDL_Rect vp {math::rect_offset(*_button_area, orig)};
SDL_Rect vp {math::rect_offset(*_click_area, orig)};
if (SDL_PointInRect(&p, &vp))
_is_hovered = true;
else

View file

@ -81,7 +81,7 @@ void abstract::Widget::_update_widget_area()
_widget_area = {
0,
0,
_viewport.w - 1,
_viewport.w - 1, // needed?
_viewport.h - 1
};
}