# HG changeset patch # User David Demelier # Date 1546622764 -3600 # Node ID e50f51702df419bfac471a400a4274383c5aa121 # Parent ac99f440ee4435a3226b77ef96955d8a3d973fb5 client: add basic button prototype, closes #908 @1h diff -r ac99f440ee44 -r e50f51702df4 libmlk-client-js/malikania/client/js/event_js_api.cpp --- a/libmlk-client-js/malikania/client/js/event_js_api.cpp Fri Jan 04 17:00:04 2019 +0100 +++ b/libmlk-client-js/malikania/client/js/event_js_api.cpp Fri Jan 04 18:26:04 2019 +0100 @@ -20,6 +20,8 @@ #include "event_js_api.hpp" +namespace duk = mlk::js::duk; + namespace mlk::client::js { namespace { @@ -31,6 +33,7 @@ mouse_wheel_event, text_event, quit_event, + message_event, }; const duk_number_list_entry codes[] = { @@ -40,6 +43,7 @@ { "MOUSE_WHEEL", static_cast(type::mouse_wheel_event) }, { "TEXT", static_cast(type::text_event) }, { "QUIT", static_cast(type::quit_event) }, + { "MESSAGE", static_cast(type::message_event) }, { nullptr, -1 } }; @@ -92,6 +96,28 @@ duk_push_int(ctx, static_cast(type::text_event)); duk_put_prop_string(ctx, -2, "type"); } + + void operator()(const message_event& ev) + { + duk::stack_guard sa(ctx); + + // TODO: create appropriate recursive function instead. + duk_push_int(ctx, static_cast(type::message_event)); + duk_put_prop_string(ctx, -2, "type"); + + if (ev.code) { + duk_push_int(ctx, ev.code.value()); + duk_put_prop_string(ctx, -2, "code"); + duk_push_string(ctx, ev.code.category().name()); + duk_put_prop_string(ctx, -2, "category"); + } + + if (ev.message.is_object()) { + duk::push(ctx, ev.message.dump(0)); + duk_json_decode(ctx, -1); + duk_put_prop_string(ctx, -2, "message"); + } + } }; } // !namespace diff -r ac99f440ee44 -r e50f51702df4 libmlk-client/malikania/client/button.cpp --- a/libmlk-client/malikania/client/button.cpp Fri Jan 04 17:00:04 2019 +0100 +++ b/libmlk-client/malikania/client/button.cpp Fri Jan 04 18:26:04 2019 +0100 @@ -39,11 +39,16 @@ text_ = std::move(text); } +void button::set_on_press(on_press_func func) noexcept +{ + on_press_ = std::move(func); +} + void button::handle_event(const event& ev) { const auto mev = std::get_if(&ev); - if (!mev) + if (!mev || !is_bound(mev->position)) return; if (mev->button == mouse::left) { @@ -56,24 +61,25 @@ void button::draw(painter& p) { - const auto& font = get_theme().get_font(); + auto& font = get_theme().get_font(); + + const auto position = get_position(); + const auto size = get_size(); const auto textsize = font.clip(text_); p.set_drawing_color({128, 68, 21}); - p.draw_rectangle({position_.x - 3, position_.y - 3, size_.width + 6, size_.height + 6}); + p.draw_rectangle({position.x - 3, position.y - 3, size.width + 6, size.height + 6}); p.set_drawing_color({85, 38, 0}); - p.draw_rectangle({position_.x - 2, position_.y - 2, size_.width + 4, size_.height + 4}); + p.draw_rectangle({position.x - 2, position.y - 2, size.width + 4, size.height + 4}); p.set_drawing_color({128, 68, 21}); - p.draw_rectangle({position_.x - 1, position_.y - 1, size_.width + 2, size_.height + 2}); + p.draw_rectangle({position.x - 1, position.y - 1, size.width + 2, size.height + 2}); p.set_drawing_color({255, 208, 170}); - p.fill_rectangle({position_.x, position_.y, size_.width, size_.height}); + p.fill_rectangle({position.x, position.y, size.width, size.height}); p.set_drawing_color(color::from_name("black")); -#if 0 - p.draw_text(text_, font, point{ - position_.x + (static_cast(size_.width) / 2) - (static_cast(textsize.width) / 2), - position_.y + (static_cast(size_.height) / 2) - (static_cast(textsize.height) / 2) + font.draw(p, text_, point{ + position.x + (static_cast(size.width) / 2) - (static_cast(textsize.width) / 2), + position.y + (static_cast(size.height) / 2) - (static_cast(textsize.height) / 2) }); -#endif } } // !mlk::client diff -r ac99f440ee44 -r e50f51702df4 libmlk-client/malikania/client/button.hpp --- a/libmlk-client/malikania/client/button.hpp Fri Jan 04 17:00:04 2019 +0100 +++ b/libmlk-client/malikania/client/button.hpp Fri Jan 04 18:26:04 2019 +0100 @@ -69,16 +69,18 @@ void set_text(std::string text) noexcept; /** + * Set the press handler. + * + * \param func the function + */ + void set_on_press(on_press_func func) noexcept; + + /** * \copydoc widget::handle_event */ void handle_event(const event& ev); /** - * Bring back other functions. - */ - using widget::draw; - - /** * \copydoc widget::draw */ void draw(painter& painter) override; diff -r ac99f440ee44 -r e50f51702df4 libmlk-client/malikania/client/event.hpp --- a/libmlk-client/malikania/client/event.hpp Fri Jan 04 17:00:04 2019 +0100 +++ b/libmlk-client/malikania/client/event.hpp Fri Jan 04 18:26:04 2019 +0100 @@ -29,6 +29,8 @@ #include +#include + #include "mouse.hpp" #include "key.hpp" @@ -50,21 +52,21 @@ struct mouse_click_event { bool pressed{true}; //!< is pressed? mouse button{mouse::none}; //!< which mouse button - point pos; //!< current mouse position + point position; //!< current mouse position }; /** * \brief Describe a mouse motion event. */ struct mouse_motion_event { - point pos; //!< current mouse position + point position; //!< current mouse position }; /** * \brief Describe mouse wheel (up/down) event. */ struct mouse_wheel_event { - point pos; //!< current mouse position + point position; //!< current mouse position }; /** @@ -81,6 +83,14 @@ }; /** + * \brief Network message event. + */ +struct message_event { + std::error_code code; + nlohmann::json message; +}; + +/** * \brief Variant with all possible events. */ using variant = std::variant< @@ -90,7 +100,8 @@ mouse_click_event, mouse_motion_event, mouse_wheel_event, - text_event + text_event, + message_event >; /** diff -r ac99f440ee44 -r e50f51702df4 libmlk-client/malikania/client/widget.cpp --- a/libmlk-client/malikania/client/widget.cpp Fri Jan 04 17:00:04 2019 +0100 +++ b/libmlk-client/malikania/client/widget.cpp Fri Jan 04 18:26:04 2019 +0100 @@ -61,4 +61,37 @@ theme_ = std::addressof(theme); } +auto widget::get_state() const noexcept -> state +{ + return state_; +} + +auto widget::is_bound(const point& position) const noexcept -> bool +{ + return position.x >= position_.x && + position.y >= position_.y && + position.x <= position_.x + size_.width && + position.y <= position_.y + size_.height; +} + +void widget::focus() noexcept +{ + state_ = state::focused; +} + +void widget::unfocus() noexcept +{ + state_ = state::normal; +} + +void widget::hide() noexcept +{ + state_ = state::hidden; +} + +void widget::show() noexcept +{ + state_ = state::normal; +} + } // !mlk::client diff -r ac99f440ee44 -r e50f51702df4 libmlk-client/malikania/client/widget.hpp --- a/libmlk-client/malikania/client/widget.hpp Fri Jan 04 17:00:04 2019 +0100 +++ b/libmlk-client/malikania/client/widget.hpp Fri Jan 04 18:26:04 2019 +0100 @@ -38,10 +38,18 @@ * \brief Abstract widget */ class widget { -protected: - theme* theme_; //!< widget theme - point position_; //!< widget position - size size_; //!< widget size +public: + enum class state { + normal, //!< widget is in normal state + hidden, //!< widget is set hidden + focused, //!< widget is focused + }; + +private: + theme* theme_; + point position_; + size size_; + state state_{state::normal}; public: /** @@ -109,6 +117,40 @@ void set_theme(theme& theme) noexcept; /** + * Get the widget state. + * + * \return the state + */ + auto get_state() const noexcept -> state; + + /** + * Check if the point is within the widget. + * + * \return true if the position is bound to the rectangle + */ + auto is_bound(const point& position) const noexcept -> bool; + + /** + * Change state to focus. + */ + virtual void focus() noexcept; + + /** + * Change state to normal. + */ + virtual void unfocus() noexcept; + + /** + * Change state to hidden. + */ + virtual void hide() noexcept; + + /** + * Change state to normal. + */ + virtual void show() noexcept; + + /** * Draw the widget. * * \param painter the painter diff -r ac99f440ee44 -r e50f51702df4 mlk-client/main.cpp --- a/mlk-client/main.cpp Fri Jan 04 17:00:04 2019 +0100 +++ b/mlk-client/main.cpp Fri Jan 04 18:26:04 2019 +0100 @@ -16,6 +16,51 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include + +#include +#include +#include +#include + +using namespace std::chrono_literals; + +int main(int argc, char** argv) +{ + mlk::client::window win(1920/2, 1080/2); + mlk::client::painter painter(win); + mlk::client::button button("click me"); + + button.set_size({200, 64}); + button.set_position({50, 50}); + button.set_on_press([] { + std::cout << "je suis clické" << std::endl; + }); + + for (;;) { + while (auto ev = win.poll()) { + if (std::get_if(&ev)) + goto end; + else + button.handle_event(ev); + } + + painter.set_drawing_color(mlk::client::color::from_hex(0xffffffff)); + painter.clear(); + button.draw(painter); + painter.present(); + + std::this_thread::sleep_for(50ms); + } + +end: + return 0; +} + +#if 0 + #include #include #include @@ -24,6 +69,8 @@ #include +// Simple javascript startup file. Don't delete. + int main(int argc, char** argv) { -- argc; @@ -57,3 +104,5 @@ return 0; } + +#endif