From 505ec2b171815a01d591ec62f9ef95836df07f6e Mon Sep 17 00:00:00 2001 From: Sander Speetjens Date: Sat, 17 Aug 2024 23:22:44 +0200 Subject: [PATCH] Initial UI in src --- src/CMakeLists.txt | 1 + src/UI/CMakeLists.txt | 31 +++++++++++ src/UI/UI.hpp | 7 +++ src/UI/UI_button.cpp | 32 ++++++++++++ src/UI/UI_button.hpp | 20 +++++++ src/UI/UI_checkbox.cpp | 83 +++++++++++++++++++++++++++++ src/UI/UI_checkbox.hpp | 27 ++++++++++ src/UI/UI_combobox.cpp | 67 ++++++++++++++++++++++++ src/UI/UI_combobox.hpp | 28 ++++++++++ src/UI/UI_item.cpp | 115 +++++++++++++++++++++++++++++++++++++++++ src/UI/UI_item.hpp | 41 +++++++++++++++ src/UI/UI_label.cpp | 22 ++++++++ src/UI/UI_label.hpp | 15 ++++++ src/UI/UI_slider.cpp | 45 ++++++++++++++++ src/UI/UI_slider.hpp | 24 +++++++++ src/UI/UI_x_boxes.cpp | 31 +++++++++++ src/UI/UI_x_boxes.hpp | 19 +++++++ 17 files changed, 608 insertions(+) create mode 100644 src/UI/CMakeLists.txt create mode 100644 src/UI/UI.hpp create mode 100644 src/UI/UI_button.cpp create mode 100644 src/UI/UI_button.hpp create mode 100644 src/UI/UI_checkbox.cpp create mode 100644 src/UI/UI_checkbox.hpp create mode 100644 src/UI/UI_combobox.cpp create mode 100644 src/UI/UI_combobox.hpp create mode 100644 src/UI/UI_item.cpp create mode 100644 src/UI/UI_item.hpp create mode 100644 src/UI/UI_label.cpp create mode 100644 src/UI/UI_label.hpp create mode 100644 src/UI/UI_slider.cpp create mode 100644 src/UI/UI_slider.hpp create mode 100644 src/UI/UI_x_boxes.cpp create mode 100644 src/UI/UI_x_boxes.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e69de29..ac9c9e3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(UI) \ No newline at end of file diff --git a/src/UI/CMakeLists.txt b/src/UI/CMakeLists.txt new file mode 100644 index 0000000..2c53f61 --- /dev/null +++ b/src/UI/CMakeLists.txt @@ -0,0 +1,31 @@ +add_library(UI) + +include(FetchContent) + +FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz) +FetchContent_MakeAvailable(json) + +target_sources(UI + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/UI_item.cpp + ${CMAKE_CURRENT_LIST_DIR}/UI_label.cpp + ${CMAKE_CURRENT_LIST_DIR}/UI_button.cpp + ${CMAKE_CURRENT_LIST_DIR}/UI_slider.cpp + ${CMAKE_CURRENT_LIST_DIR}/UI_x_boxes.cpp + ${CMAKE_CURRENT_LIST_DIR}/UI_combobox.cpp + ${CMAKE_CURRENT_LIST_DIR}/UI_checkbox.cpp +) + +target_include_directories(UI + PUBLIC + ${CMAKE_CURRENT_LIST_DIR} + PRIVATE + ${PROJECT_DIR}/external/** + ${CMAKE_BINARY_DIR}/** +) + +target_link_libraries(UI + PUBLIC + Color + nlohmann_json::nlohmann_json +) \ No newline at end of file diff --git a/src/UI/UI.hpp b/src/UI/UI.hpp new file mode 100644 index 0000000..df7df51 --- /dev/null +++ b/src/UI/UI.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "UI_button.hpp" +#include "UI_checkbox.hpp" +#include "UI_combobox.hpp" +#include "UI_label.hpp" +#include "UI_slider.hpp" \ No newline at end of file diff --git a/src/UI/UI_button.cpp b/src/UI/UI_button.cpp new file mode 100644 index 0000000..16a429d --- /dev/null +++ b/src/UI/UI_button.cpp @@ -0,0 +1,32 @@ +#include "UI_button.hpp" + +UI_button::UI_button(std::string id, std::string text, Color fg_color, Color bg_color, UI_button_on_click on_click) + : UI_item(id, UI_BUTTON_TYPE, text, 12, fg_color, bg_color) +{ + this->p_on_click = on_click; +} + +UI_button::UI_button(const json& j) + : UI_item(UI_BUTTON_TYPE) +{ + from_json(j); +} + +void UI_button::from_json(const json& j) +{ + UI_item::from_json(j); +} + +json UI_button::to_json() const +{ + json j = UI_item::to_json(); + return j; +} + +void UI_button::click() const +{ + if (p_on_click != nullptr) + { + p_on_click(p_id); + } +} diff --git a/src/UI/UI_button.hpp b/src/UI/UI_button.hpp new file mode 100644 index 0000000..6f7fd01 --- /dev/null +++ b/src/UI/UI_button.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "UI_item.hpp" + +#define UI_BUTTON_TYPE std::string("UIButton") +typedef void(*UI_button_on_click)(std::string id); + +class UI_button : public UI_item +{ + public: + UI_button(std::string id, std::string text, Color fg_color, Color bg_color, UI_button_on_click on_click); + UI_button(const json& j); + + void from_json(const json& j) override; + json to_json() const override; + + void click() const; + private: + UI_button_on_click p_on_click = nullptr; +}; \ No newline at end of file diff --git a/src/UI/UI_checkbox.cpp b/src/UI/UI_checkbox.cpp new file mode 100644 index 0000000..b00a958 --- /dev/null +++ b/src/UI/UI_checkbox.cpp @@ -0,0 +1,83 @@ +#include "UI_checkbox.hpp" + +UI_checkbox::UI_checkbox() + : UI_x_boxes(UI_CHECKBOX_TYPE), p_selected(), p_on_change(nullptr) +{ +} + +UI_checkbox::UI_checkbox(std::string id, std::string text, Color fg_color, Color bg_color, std::vector options, UI_checkbox_on_change on_change) + : UI_x_boxes(id, UI_CHECKBOX_TYPE, text, fg_color, bg_color, options), p_selected(), p_on_change(on_change) +{ +} + +UI_checkbox::UI_checkbox(const json& j) : +UI_x_boxes(UI_CHECKBOX_TYPE), p_selected(), p_on_change(nullptr) +{ + from_json(j); +} + +void UI_checkbox::toggle_selected(size_t selected) +{ + if (selected >= p_options.size()) + return; + + if (p_selected[selected] != p_selected[selected]) + { + p_selected[selected] = !p_selected[selected]; + if (p_on_change != nullptr) + { + p_on_change(p_id, selected_text()); + } + } +} + +void UI_checkbox::toggle_selected(std::string selected) +{ + for (size_t i = 0; i < p_options.size(); i++) + { + if (p_options[i] == selected) + { + toggle_selected(i); + return; + } + } +} + +std::vector UI_checkbox::selected() const +{ + return p_selected; +} + +std::vector UI_checkbox::selected_text() const +{ + std::vector selected_text; + for (size_t i = 0; i < p_options.size(); i++) + { + if (p_selected[i]) + { + selected_text.push_back(p_options[i]); + } + } + return selected_text; +} + +void UI_checkbox::from_json(const json& j) +{ + UI_x_boxes::from_json(j); + + if (j.contains("selected")) + { + p_selected.clear(); + for (auto selected : j["selected"]) + { + p_selected.push_back(selected); + } + } +} + +json UI_checkbox::to_json() const +{ + json j = UI_x_boxes::to_json(); + j["selected"] = p_selected; + return j; +} diff --git a/src/UI/UI_checkbox.hpp b/src/UI/UI_checkbox.hpp new file mode 100644 index 0000000..0200c98 --- /dev/null +++ b/src/UI/UI_checkbox.hpp @@ -0,0 +1,27 @@ +#pragma once +#include +#include "UI_item.hpp" +#include "UI_x_boxes.hpp" + +#define UI_CHECKBOX_TYPE std::string("UIcheckbox") +typedef void (*UI_checkbox_on_change) (std::string id, std::vector selected); + +class UI_checkbox : UI_x_boxes +{ + public: + UI_checkbox(); + UI_checkbox(std::string id, std::string text, Color fg_color, Color bg_color, std::vector options, UI_checkbox_on_change on_change = nullptr); + UI_checkbox(const json& j); + + void toggle_selected(size_t selected); + void toggle_selected(std::string selected); + std::vector selected() const; + std::vector selected_text() const; + + void from_json(const json& j) override; + json to_json() const override; + private: + std::vector p_selected; + + UI_checkbox_on_change p_on_change; +}; \ No newline at end of file diff --git a/src/UI/UI_combobox.cpp b/src/UI/UI_combobox.cpp new file mode 100644 index 0000000..803552f --- /dev/null +++ b/src/UI/UI_combobox.cpp @@ -0,0 +1,67 @@ +#include "UI_combobox.hpp" + +UI_combobox::UI_combobox() + : UI_x_boxes(UI_COMBOBOX_TYPE) +{ +} + +UI_combobox::UI_combobox(std::string id, std::string text, Color fg_color, Color bg_color, std::vector options, int selected, UI_combobox_on_change on_change) + : UI_x_boxes(id, UI_COMBOBOX_TYPE, text, fg_color, bg_color, options), p_selected(selected), p_on_change(on_change) +{ +} + +UI_combobox::UI_combobox(std::string id, std::string text, Color fg_color, Color bg_color, std::vector options, UI_combobox_on_change on_change) + : UI_x_boxes(id, UI_COMBOBOX_TYPE, text, fg_color, bg_color, options), p_selected(0), p_on_change(on_change) +{ +} + +UI_combobox::UI_combobox(const json& j) +: UI_x_boxes(UI_COMBOBOX_TYPE), p_on_change(nullptr) +{ + from_json(j); +} + +void UI_combobox::set_selected(size_t selected) +{ + if (selected != p_selected) + { + p_selected = selected; + if (p_on_change != nullptr) + { + p_on_change(p_id, selected); + } + } +} + +void UI_combobox::set_selected(std::string selected) +{ + for (size_t i = 0; i < p_options.size(); i++) + { + if (p_options[i] == selected) + { + set_selected(i); + return; + } + } +} + +size_t UI_combobox::selected() const +{ + return p_selected; +} + +std::string UI_combobox::selected_text() const +{ + return p_options[p_selected]; +} + +void UI_combobox::from_json(const json& j) +{ + UI_x_boxes::from_json(j); +} + +json UI_combobox::to_json() const +{ + json j = UI_x_boxes::to_json(); + return j; +} \ No newline at end of file diff --git a/src/UI/UI_combobox.hpp b/src/UI/UI_combobox.hpp new file mode 100644 index 0000000..6009610 --- /dev/null +++ b/src/UI/UI_combobox.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "UI_item.hpp" +#include "UI_x_boxes.hpp" + +#define UI_COMBOBOX_TYPE std::string("UIcombobox") +typedef void (*UI_combobox_on_change) (std::string id, int selected); + +class UI_combobox : public UI_x_boxes +{ + public: + UI_combobox(); + UI_combobox(std::string id, std::string text, Color fg_color, Color bg_color, std::vector options, int selected, UI_combobox_on_change on_change = nullptr); + UI_combobox(std::string id, std::string text, Color fg_color, Color bg_color, std::vector options, UI_combobox_on_change on_change = nullptr); + UI_combobox(const json& j); + + void set_selected(size_t selected); + void set_selected(std::string selected); + size_t selected() const; + std::string selected_text() const; + + void from_json(const json& j) override; + json to_json() const override; + private: + size_t p_selected; + + UI_combobox_on_change p_on_change; +}; \ No newline at end of file diff --git a/src/UI/UI_item.cpp b/src/UI/UI_item.cpp new file mode 100644 index 0000000..a9f91bd --- /dev/null +++ b/src/UI/UI_item.cpp @@ -0,0 +1,115 @@ +#include "UI_item.hpp" + +UI_item::UI_item(std::string id, std::string type, std::string text, uint8_t text_size, Color fg_color, Color bg_color) + : p_id(id), p_type(type), p_text(text), p_text_size(text_size), p_fg_color(fg_color), p_bg_color(bg_color) +{ +} + +UI_item::UI_item(std::string type) + : p_id(""), p_type(type), p_text(""), p_text_size(12), p_fg_color(Color::Black), p_bg_color(Color::White) +{ +} + +UI_item::UI_item(const json& j) +{ + from_json(j); +} + +std::string UI_item::id() const +{ + return p_id; +} + +std::string UI_item::type() const +{ + return p_type; +} + +bool UI_item::is_type(json j) +{ + if (!j.contains("type")) + { + return false; + } + return j.at("type") == p_type; +} + +void UI_item::set_text(std::string text) +{ + if (this->p_text != text) + { + this->p_text = text; + } +} + +std::string UI_item::text() const +{ + return p_text; +} + +void UI_item::set_text_size(uint8_t text_size) +{ + if (this->p_text_size != text_size) + { + this->p_text_size = text_size; + } +} + +uint8_t UI_item::text_size() const +{ + return p_text_size; +} + +void UI_item::set_fg_color(Color fg_color) +{ + if (this->p_fg_color != fg_color) + { + this->p_fg_color = fg_color; + } +} + +Color UI_item::fg_color() const +{ + return p_fg_color; +} + +void UI_item::set_bg_color(Color bg_color) +{ + if (this->p_bg_color != bg_color) + { + this->p_bg_color = bg_color; + } +} + +Color UI_item::bg_color() const +{ + return p_bg_color; +} + + +void UI_item::from_json(const json& j) +{ + if (!is_type(j)) + return; + j.at("id").get_to(p_id); + j.at("text").get_to(p_text); + j.at("text_size").get_to(p_text_size); + std::string color; + j.at("fg_color").get_to(color); + p_fg_color = Color(color); + color.clear(); + j.at("bg_color").get_to(color); + p_bg_color = Color(color); +} + +json UI_item::to_json() const +{ + json j; + j["id"] = p_id; + j["type"] = p_type; + j["text"] = p_text; + j["text_size"] = p_text_size; + j["fg_color"] = p_fg_color.to_hex(); + j["bg_color"] = p_bg_color.to_hex(); + return j; +} \ No newline at end of file diff --git a/src/UI/UI_item.hpp b/src/UI/UI_item.hpp new file mode 100644 index 0000000..5687956 --- /dev/null +++ b/src/UI/UI_item.hpp @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include +#include "color.hpp" +using json = nlohmann::json; + +class UI_item { + public: + UI_item(std::string type); + UI_item(std::string id, std::string type, std::string text, uint8_t text_size, Color fg_color, Color bg_color); + UI_item(const json& j); + + std::string id() const; + std::string type() const; + bool is_type(json j); + + void set_text(std::string text); + std::string text() const; + + void set_text_size(uint8_t text_size); + uint8_t text_size() const; + + void set_fg_color(Color fg_color); + Color fg_color() const; + + void set_bg_color(Color bg_color); + Color bg_color() const; + + virtual void from_json(const json& j); + + virtual json to_json() const; + + protected: + std::string p_id; + std::string p_type; + std::string p_text; + uint8_t p_text_size; + Color p_fg_color; + Color p_bg_color; +}; \ No newline at end of file diff --git a/src/UI/UI_label.cpp b/src/UI/UI_label.cpp new file mode 100644 index 0000000..082c84e --- /dev/null +++ b/src/UI/UI_label.cpp @@ -0,0 +1,22 @@ +#include "UI_label.hpp" + +UI_label::UI_label(std::string id, std::string text, Color fg_color, Color bg_color) + : UI_item(id, UI_LABEL_TYPE, text, 12, fg_color, bg_color) +{ +} + +UI_label::UI_label(const json& j) + : UI_item(UI_LABEL_TYPE) +{ + from_json(j); +} + +void UI_label::from_json(const json& j) +{ + UI_item::from_json(j); +} + +json UI_label::to_json() const +{ + return UI_item::to_json(); +} \ No newline at end of file diff --git a/src/UI/UI_label.hpp b/src/UI/UI_label.hpp new file mode 100644 index 0000000..1454136 --- /dev/null +++ b/src/UI/UI_label.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include "UI_item.hpp" + +#define UI_LABEL_TYPE std::string("UIlabel") + +class UI_label : public UI_item +{ +public: + UI_label(std::string id, std::string text, Color fg_color, Color bg_color); + UI_label(const json& j); + + void from_json(const json& j) override; + json to_json() const override; +}; \ No newline at end of file diff --git a/src/UI/UI_slider.cpp b/src/UI/UI_slider.cpp new file mode 100644 index 0000000..3ae2645 --- /dev/null +++ b/src/UI/UI_slider.cpp @@ -0,0 +1,45 @@ +#include "UI_slider.hpp" + +UI_slider::UI_slider(std::string id, std::string text, Color fg_color, Color bg_color, double min, double max, double value, UI_slider_on_change on_change) + : UI_item(id, UI_SLIDER_TYPE, text, 12, fg_color, bg_color), p_min(min), p_max(max), p_value(value) +{ + this->p_on_change = on_change; +} + +UI_slider::UI_slider(const json& j) +: UI_item(UI_SLIDER_TYPE) +{ + from_json(j); +} + +void UI_slider::set_value(double value) +{ + if (p_on_change != nullptr) + { + this->p_value = value; + p_on_change(p_id, value); + } +} + +double UI_slider::value() const +{ + return p_value; +} + +void UI_slider::from_json(const json& j) +{ + UI_item::from_json(j); + + this->p_min = j["min"]; + this->p_max = j["max"]; + this->p_value = j["value"]; +} + +json UI_slider::to_json() const +{ + json j = UI_item::to_json(); + j["min"] = this->p_min; + j["max"] = this->p_max; + j["value"] = this->p_value; + return j; +} \ No newline at end of file diff --git a/src/UI/UI_slider.hpp b/src/UI/UI_slider.hpp new file mode 100644 index 0000000..33afaa6 --- /dev/null +++ b/src/UI/UI_slider.hpp @@ -0,0 +1,24 @@ +#pragma once +#include "UI_item.hpp" + +#define UI_SLIDER_TYPE std::string("UISlider") +typedef void(*UI_slider_on_change)(std::string, double value); + +class UI_slider : public UI_item +{ + public: + UI_slider(std::string id, std::string text, Color fg_color, Color bg_color, double min, double max, double value, UI_slider_on_change on_change); + UI_slider(const json& j); + + void set_value(double value); + double value() const; + + void from_json(const json& j) override; + json to_json() const override; + private: + double p_min; + double p_max; + double p_value; + + UI_slider_on_change p_on_change; +}; \ No newline at end of file diff --git a/src/UI/UI_x_boxes.cpp b/src/UI/UI_x_boxes.cpp new file mode 100644 index 0000000..51ad963 --- /dev/null +++ b/src/UI/UI_x_boxes.cpp @@ -0,0 +1,31 @@ +#include "UI_x_boxes.hpp" + +UI_x_boxes::UI_x_boxes(std::string type) + : UI_item(type), p_options() +{ +} + +UI_x_boxes::UI_x_boxes(std::string id, std::string type, std::string text, Color fg_color, Color bg_color, std::vector options) + : UI_item(id, type, text, 12, fg_color, bg_color), p_options(options) +{ +} + +void UI_x_boxes::from_json(const json& j) +{ + UI_item::from_json(j); + if (j.contains("options")) + { + this->p_options.clear(); + for (auto option : j["options"]) + { + this->p_options.push_back(option); + } + } +} + +json UI_x_boxes::to_json() const +{ + json j = UI_item::to_json(); + j["options"] = this->p_options; + return j; +} \ No newline at end of file diff --git a/src/UI/UI_x_boxes.hpp b/src/UI/UI_x_boxes.hpp new file mode 100644 index 0000000..94c47a4 --- /dev/null +++ b/src/UI/UI_x_boxes.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "UI_item.hpp" + +class UI_x_boxes : public UI_item +{ + public: + UI_x_boxes(std::string type); + UI_x_boxes(std::string id, std::string type, std::string text, Color fg_color, Color bg_color, std::vector options); + + void from_json(const json& j) override; + json to_json() const override; + protected: + std::vector p_options; + // std::vector p_selected_multi; + // size_t p_selected; + + // void (*p_on_change) (std::string id, int selected); +}; \ No newline at end of file