LiteLoaderBDS-1.16.40/LiteLoader/Header/FormUI.h
2022-09-21 19:47:03 +08:00

447 lines
15 KiB
C++

#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 <key> of std::map "result" equals the first argument "name" you pass to these elements
// So, "name" must be *unique* or error will occur
//
////////////////////////////////////////////////////////////////////////
#include <utility>
#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<void(Player*)>;
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<string> options;
int def;
public:
inline Dropdown(const string& name, string title, const vector<string>& 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<string>& _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<string> options;
int def;
public:
inline StepSlider(const string& name, string title, const vector<string>& 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<string>& _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<void(Player*, int)>;
string title, content;
vector<std::shared_ptr<SimpleFormElement>> elements;
Callback callback;
public:
SimpleForm(string title, string content)
: title(std::move(title))
, content(std::move(content)) {
}
template <typename T, typename... Args>
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<void(Player*, bool)>;
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 <typename T, typename... Args>
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<void(Player*, std::map<string, std::shared_ptr<CustomFormElement>>)>;
using Callback2 = std::function<void(Player*, std::string)>;
string title;
std::vector<std::pair<string, std::shared_ptr<CustomFormElement>>> elements;
Callback callback;
public:
explicit CustomForm(string title)
: title(std::move(title)) {
}
template <typename T, typename... Args>
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<string>& 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<string>& 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 <typename T>
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