#pragma once //////////////////////////////////////////////////////////////////////// // Form UI Utility - Help you to build forms and options more easily // // [Example - Simple Form] // - Form that contains several buttons (with optional image) // - Let the player choose an option from multiple options // // SimpleForm form("Welcome to shop", "Choose what you want to do..."); // Initialize the form with title and content // form.addButton("Buy", "textures/items/apple", // Add a button "Buy" with texture image // [](Player* pl) { pl->sendText("To buy something..."); }) // Buy's callback function // // .addButton("Sell", "https://xxx.com/xxx.png", // Add a button "Sell" with online image // [](Player* pl) { pl->sendText("To sell something..."); }) // Sell's callback function // // .addButton("Settings", "", // Add a button "Settings" with no image // [](Player* pl) { pl->sendText("Get into settings..."); }) // Settings's callback function // // .addButton("Exit") // Add a single button "Exit" // .sendTo(Level::getPlayer("John")); // Send the form to a player called "John" // // // [Example - Modal Form] // - Form with Confirm and Cancel buttons // - Let the player confirm or cancel an action // // ModalForm form("Confirm the action", "Do you want that?", "Yes", "Nope"); // Initialize the form with title, content and two buttons ("Yes", "Nope") // form.sendTo(Level::getPlayer("S3v3N1ce"), // Send the form to a player called "S3v3N1ce" // [](Player* player, bool isConfirm) // Callback function to process the result // { // if (isConfirm) // Player pressed button "Yes" // player->sendText("Okay, let's go"); // else // Player pressed button "Nope" // player->sendText("Hm, suit yourself"); // }); // // // [Example - Custom Form] // - Form that contains some kinds of elements (like input line, toggle, dropdown, ....) // - Let the player provide some detailed information // // CustomForm form2("Information Collection Form"); // Initialize the form with title // form2.addLabel("label1", "Personal Information") // Add a label shows "Personal Information" // .addInput("username", "Your Name") // Add an input line to gather player's name // .addDropdown("sex", "Your Sex", { "Male","Female","Secret" }) // Add a dropdown to gather player's sex // .addSlider("age", "Your Age", 3, 100) // Add a slider to gather player's age // // .addLabel("label2", "MC Information") // Add a label shows "MC Information" // .addToggle("licensed", "Purchased a licensed Minecraft?", true) // Add a toggle about whether he buys a licensed mc or not // .addStepSlider("skill", "Skill Lvl", { "Beginner", "Amateur", "Pro" }) // Add a step slider shows his game skill level // // .sendTo(Level::getPlayer("yqs112358"), // Send the form to a player called "yqs112358" // [](Player* player, auto result) // Callback function to process the result // { // if (result.empty()) // Player cancelled the form // return; // player->sendText("You have commited the form."); // player->sendFormattedText("Your name: {}", result["username"]->getString()); // player->sendFormattedText("Your sex: {}", result["sex"]->getString()); // player->sendFormattedText("Your age: {}", result["age"]->getNumber()); // player->sendFormattedText("Your license: {}", result["licensed"]->getBool() ? "yes" : "no"); // player->sendFormattedText("Your skill level: {}:", result["skill"]->getString()); // }); // // // Tips: The of std::map "result" equals the first argument "name" you pass to these elements // So, "name" must be *unique* or error will occur // //////////////////////////////////////////////////////////////////////// #include #include "Global.h" class ServerPlayer; class Player; namespace Form { //////////////////////////////// Simple Form Elements //////////////////////////////// class SimpleFormElement { protected: virtual string serialize() = 0; friend class SimpleForm; }; class Button : public SimpleFormElement { protected: LIAPI string serialize() override; public: using ButtonCallback = std::function; string text, image; ButtonCallback callback; public: inline explicit Button(string text, string image = "", ButtonCallback callback = ButtonCallback()) : text(std::move(text)) , image(std::move(image)) , callback(std::move(callback)) { } inline void setText(const string& _text) { this->text = _text; } inline void setImage(const string& _image) { this->image = _image; } inline void setCallback(ButtonCallback _callback) { this->callback = std::move(_callback); } }; //////////////////////////////// Custom Form Elements //////////////////////////////// class CustomFormElement { protected: LIAPI virtual string serialize() = 0; friend class CustomForm; public: enum class Type { Label, Input, Toggle, Dropdown, Slider, StepSlider }; string name; string value; Type type{}; inline void setName(const string& _name) { this->name = _name; } inline virtual Type getType() = 0; LIAPI std::string getString(); [[deprecated("Please use getInt")]] LIAPI int getNumber(); LIAPI int getInt(); LIAPI float getFloat(); LIAPI double getDouble(); LIAPI bool getBool(); }; class Label : public CustomFormElement { protected: LIAPI string serialize() override; public: string text; public: inline Label(const string& name, string text) : text(std::move(text)) { setName(name); } inline Type getType() override { return Type::Label; } inline void setText(const string& _text) { this->text = _text; } }; class Input : public CustomFormElement { protected: LIAPI string serialize() override; public: string title, placeholder, def; inline Input(const string& name, string title, string placeholder = "", string def = "") : title(std::move(title)) , placeholder(std::move(placeholder)) , def(std::move(def)) { setName(name); } inline Type getType() override { return Type::Input; } inline void setTitle(const string& _title) { this->title = _title; } inline void setPlaceHolder(const string& _placeholder) { this->placeholder = _placeholder; } inline void setDefault(const string& _def) { this->def = _def; } }; class Toggle : public CustomFormElement { protected: LIAPI string serialize() override; public: public: string title; bool def; public: inline Toggle(const string& name, string title, bool def = false) : title(std::move(title)) , def(def) { setName(name); } inline virtual Type getType() override { return Type::Toggle; } inline void setTitle(const string& _title) { this->title = _title; } inline void setDefault(bool _def) { this->def = _def; } }; class Dropdown : public CustomFormElement { protected: LIAPI string serialize() override; public: string title; vector options; int def; public: inline Dropdown(const string& name, string title, const vector& options, int defId = 0) : title(std::move(title)) , options(options) , def(defId) { setName(name); } inline Type getType() override { return Type::Dropdown; } inline void setTitle(const string& _title) { this->title = _title; } inline void setOptions(const vector& _options) { this->options = _options; } inline void addOption(const string& option) { options.push_back(option); } inline void setDefault(int defId) { this->def = defId; } }; class Slider : public CustomFormElement { protected: LIAPI string serialize() override; public: string title; double minValue, maxValue, step, def; public: inline Slider(const string& name, string title, double minValue, double maxValue, double step = 1, double def = 0) : title(std::move(title)) , minValue(minValue) , maxValue(maxValue) , step(step) , def(def) { setName(name); } inline Type getType() override { return Type::Slider; } inline void setTitle(const string& _title) { this->title = _title; } inline void setMin(double _minValue) { this->minValue = _minValue; } inline void setMax(double _maxValue) { this->maxValue = _maxValue; } inline void setStep(double _step) { this->step = _step; } inline void setDefault(double _def) { this->def = _def; } }; class StepSlider : public CustomFormElement { protected: LIAPI string serialize() override; public: string title; vector options; int def; public: inline StepSlider(const string& name, string title, const vector& options, int defId = 0) : title(std::move(title)) , options(options) , def(defId) { setName(name); } inline Type getType() override { return Type::StepSlider; } inline void setTitle(const string& _title) { this->title = _title; } inline void setOptions(const vector& _options) { this->options = _options; } inline void addOption(const string& option) { options.push_back(option); } inline void setDefault(int defId) { this->def = defId; } }; //////////////////////////////// Forms //////////////////////////////// class FormImpl { protected: // fifo_json json; virtual string serialize() = 0; }; class SimpleForm : public FormImpl { protected: LIAPI string serialize() override; public: using Callback = std::function; string title, content; vector> elements; Callback callback; public: SimpleForm(string title, string content) : title(std::move(title)) , content(std::move(content)) { } template SimpleForm(const string& title, const string& content, T element, Args... args) { append(element); SimpleForm(title, content, args...); } LIAPI SimpleForm& setTitle(const string& title); LIAPI SimpleForm& setContent(const string& content); LIAPI SimpleForm& addButton(string text, string image = "", Button::ButtonCallback callback = Button::ButtonCallback()); LIAPI SimpleForm& append(const Button& element); LIAPI bool sendTo(Player* player, Callback callback = Callback()); }; class ModalForm : public FormImpl { protected: LIAPI string serialize() override; public: using Callback = std::function; string title, content, confirmButton, cancelButton; Callback callback; public: ModalForm(string title, string content, string button1, string button2) : title(std::move(title)) , content(std::move(content)) , confirmButton(std::move(button1)) , cancelButton(std::move(button2)) { } template ModalForm(const string& title, const string& content, const string& confirmButton, const string& cancelButton, Args... args) { ModalForm(title, content, confirmButton, cancelButton, args...); } LIAPI ModalForm& setTitle(const string& title); LIAPI ModalForm& setContent(const string& content); LIAPI ModalForm& setConfirmButton(const string& text); LIAPI ModalForm& setCancelButton(const string& text); LIAPI bool sendTo(Player* player, Callback callback = Callback()); }; class CustomForm : public FormImpl { protected: LIAPI string serialize() override; public: using Callback = std::function>)>; using Callback2 = std::function; string title; std::vector>> elements; Callback callback; public: explicit CustomForm(string title) : title(std::move(title)) { } template CustomForm(const string& title, T element, Args... args) { append(element); CustomForm(title, args...); } LIAPI CustomForm& setTitle(const string& title); LIAPI CustomForm& addLabel(const string& name, string text); LIAPI CustomForm& addInput(const string& name, string title, string placeholder = "", string def = ""); LIAPI CustomForm& addToggle(const string& name, string title, bool def = false); LIAPI CustomForm& addDropdown(const string& name, string title, const vector& options, int defId = 0); LIAPI CustomForm& addSlider(const string& name, string title, double min, double max, double step = 1, double def = 0); LIAPI CustomForm& addStepSlider(const string& name, string title, const vector& options, int defId = 0); LIAPI CustomForm& append(const Label& element); LIAPI CustomForm& append(const Input& element); LIAPI CustomForm& append(const Toggle& element); LIAPI CustomForm& append(const Dropdown& element); LIAPI CustomForm& append(const Slider& element); LIAPI CustomForm& append(const StepSlider& element); LIAPI bool sendTo(Player* player, Callback callback); LIAPI bool sendToForRawJson(Player* player, Callback2 callback); LIAPI CustomFormElement* getElement(const string& name); LIAPI CustomFormElement* getElement(int index); LIAPI CustomFormElement::Type getType(int index); LIAPI string getString(const string& name); [[deprecated("Please use getInt")]] LIAPI int getNumber(const string& name); LIAPI int getInt(const string& name); LIAPI float getFloat(const string& name); LIAPI double getDouble(const string& name); LIAPI bool getBool(const string& name); LIAPI string getString(int index); [[deprecated("Please use getInt")]] LIAPI int getNumber(int index); LIAPI int getInt(int index); LIAPI float getFloat(int index); LIAPI double getDouble(int index); LIAPI bool getBool(int index); // Tool Functions template inline void setValue(int index, T value) { elements[index].second->value = std::to_string(value); } inline void setValue(int index, string value) { elements[index].second->value = value; } }; } // namespace Form