From 945d83816603382dbe7672e9f8ed2437e1cf5701 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 15 Aug 2023 15:33:44 +0200 Subject: [PATCH] libui: Add Buttons --- apps/taskbar.cpp | 11 ++++++- libui/CMakeLists.txt | 1 + libui/include/ui/Button.h | 35 ++++++++++++++++++++ libui/src/App.cpp | 1 + libui/src/Button.cpp | 68 +++++++++++++++++++++++++++++++++++++++ libui/src/Container.cpp | 1 + 6 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 libui/include/ui/Button.h create mode 100644 libui/src/Button.cpp diff --git a/apps/taskbar.cpp b/apps/taskbar.cpp index 975df284..646262af 100644 --- a/apps/taskbar.cpp +++ b/apps/taskbar.cpp @@ -1,4 +1,6 @@ +#include #include +#include #include #include #include @@ -19,8 +21,15 @@ Result luna_main(int argc, char** argv) ui::HorizontalLayout layout(ui::AdjustHeight::Yes, ui::AdjustWidth::No); window->set_main_widget(layout); + ui::Button button({ 0, 0, 50, 50 }); + layout.add_widget(button); + ui::Container container({ 0, 0, 50, 50 }, ui::VerticalAlignment::Center, ui::HorizontalAlignment::Center); - layout.add_widget(container); + button.set_widget(container); + button.set_action([] { + StringView args[] = { "/usr/bin/gclient" }; + os::Process::spawn("/usr/bin/gclient", Slice { args, 1 }, false); + }); auto image = TRY(ui::ImageWidget::load("/usr/share/icons/32x32/start-icon.tga")); container.set_widget(*image); diff --git a/libui/CMakeLists.txt b/libui/CMakeLists.txt index 9885e476..415f6bde 100644 --- a/libui/CMakeLists.txt +++ b/libui/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES src/Layout.cpp src/Alignment.cpp src/Container.cpp + src/Button.cpp ) add_library(ui ${SOURCES}) diff --git a/libui/include/ui/Button.h b/libui/include/ui/Button.h new file mode 100644 index 00000000..f2715f5b --- /dev/null +++ b/libui/include/ui/Button.h @@ -0,0 +1,35 @@ +/** + * @file Button.h + * @author apio (cloudapio.eu) + * @brief A clickable component that triggers an action when pressed. + * + * @copyright Copyright (c) 2023, the Luna authors. + * + */ + +#pragma once +#include + +namespace ui +{ + class Button : public Widget + { + public: + Button(Rect rect); + + void set_widget(Widget& widget); + void set_action(void (*action)(void)); + + Result handle_mouse_move(Point position) override; + Result handle_mouse_leave(Point position) override; + Result handle_mouse_down(Point position, int buttons) override; + Result handle_mouse_up(Point position, int buttons) override; + Result draw(Canvas& canvas) override; + + private: + bool m_hovered { false }; + bool m_clicked { false }; + Widget* m_child; + void (*m_action)(void); + }; +} diff --git a/libui/src/App.cpp b/libui/src/App.cpp index 035820d3..eb067312 100644 --- a/libui/src/App.cpp +++ b/libui/src/App.cpp @@ -105,6 +105,7 @@ namespace ui TRY(m_client->recv_typed(request)); auto* window = find_window(request.window); window->handle_mouse_move(request.position); + window->handle_mouse_buttons(request.position, request.buttons); window->draw(); return {}; } diff --git a/libui/src/Button.cpp b/libui/src/Button.cpp new file mode 100644 index 00000000..487cfa53 --- /dev/null +++ b/libui/src/Button.cpp @@ -0,0 +1,68 @@ +/** + * @file Button.cpp + * @author apio (cloudapio.eu) + * @brief A clickable component that triggers an action when pressed. + * + * @copyright Copyright (c) 2023, the Luna authors. + * + */ + +#include +#include + +namespace ui +{ + Button::Button(Rect rect) + { + m_rect = rect; + } + + void Button::set_widget(Widget& widget) + { + widget.rect() = m_rect; + m_child = &widget; + widget.set_parent(this); + } + + void Button::set_action(void (*action)(void)) + { + m_action = action; + } + + Result Button::handle_mouse_move(Point position) + { + m_hovered = true; + return m_child->handle_mouse_move(position); + } + + Result Button::handle_mouse_leave(Point position) + { + m_hovered = m_clicked = false; + return m_child->handle_mouse_leave(position); + } + + Result Button::handle_mouse_down(Point position, int buttons) + { + auto result = TRY(m_child->handle_mouse_down(position, buttons)); + if (result == EventResult::DidNotHandle) + { + if (!m_clicked && (buttons == ui::MouseButtons::LEFT)) + { + m_clicked = true; + m_action(); + } + } + return EventResult::DidHandle; + } + + Result Button::handle_mouse_up(Point position, int buttons) + { + if (buttons & ui::MouseButtons::LEFT) m_clicked = false; + return m_child->handle_mouse_up(position, buttons); + } + + Result Button::draw(Canvas& canvas) + { + return m_child->draw(canvas); + } +} diff --git a/libui/src/Container.cpp b/libui/src/Container.cpp index e40b1b55..876013ac 100644 --- a/libui/src/Container.cpp +++ b/libui/src/Container.cpp @@ -21,6 +21,7 @@ namespace ui { m_widget = &widget; widget.rect() = ui::align(m_rect, widget.rect(), m_valign, m_halign); + widget.set_parent(this); } Result Container::handle_mouse_move(Point position)