The complete source code of IdealIRC
http://www.idealirc.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
4.6 KiB
199 lines
4.6 KiB
#include "Dialog.h"
|
|
#include "ScriptException.h"
|
|
#include <unordered_map>
|
|
|
|
struct DialogWidgetPriv
|
|
{
|
|
explicit DialogWidgetPriv(const std::string& name_, DialogWidget::Type type_);
|
|
std::string name;
|
|
DialogWidget::Type type;
|
|
std::unordered_map<std::string, ValueHolder> attrs;
|
|
std::unordered_map<std::string, Scope> hooks;
|
|
};
|
|
|
|
struct DialogPriv
|
|
{
|
|
explicit DialogPriv(const std::string& name_);
|
|
std::string name;
|
|
std::unordered_map<std::string, ValueHolder> attrs;
|
|
std::unordered_map<std::string, DialogWidget> widgets;
|
|
std::vector<std::string> widgetNames; // Need this since we cannot iterate over 'widgets' due to deleted copy ctor.
|
|
std::unordered_map<std::string, Scope> hooks;
|
|
};
|
|
|
|
|
|
DialogPriv::DialogPriv(const std::string& name_)
|
|
: name(name_)
|
|
{}
|
|
|
|
DialogWidgetPriv::DialogWidgetPriv(const std::string& name_, DialogWidget::Type type_)
|
|
: name(name_)
|
|
, type(type_)
|
|
{}
|
|
|
|
std::optional<DialogWidget::Type> DialogWidget::strToType(const std::string& stype)
|
|
{
|
|
if (stype == "label")
|
|
return Type::Label;
|
|
else if (stype == "button")
|
|
return Type::Button;
|
|
else if (stype == "textline")
|
|
return Type::Textline;
|
|
else if (stype == "textbox")
|
|
return Type::Textbox;
|
|
else if (stype == "spinbox")
|
|
return Type::Spinbox;
|
|
else if (stype == "listbox")
|
|
return Type::Listbox;
|
|
else if (stype == "combobox")
|
|
return Type::Combobox;
|
|
else if (stype == "table")
|
|
return Type::Table;
|
|
else if (stype == "tree")
|
|
return Type::Tree;
|
|
else if (stype == "groupbox")
|
|
return Type::Groupbox;
|
|
else if (stype == "tab")
|
|
return Type::Tab;
|
|
else if (stype == "radio")
|
|
return Type::Radio;
|
|
else if (stype == "checkbox")
|
|
return Type::Checkbox;
|
|
else if (stype == "vscroll")
|
|
return Type::Vscroll;
|
|
else if (stype == "hscroll")
|
|
return Type::Hscroll;
|
|
else if (stype == "canvas")
|
|
return Type::Canvas;
|
|
else
|
|
return std::nullopt;
|
|
}
|
|
|
|
DialogWidget::DialogWidget(const std::string& name, Type type)
|
|
: mp(new DialogWidgetPriv(name, type))
|
|
{}
|
|
|
|
DialogWidget::DialogWidget(DialogWidget&& other)
|
|
: mp(std::move(other.mp))
|
|
{}
|
|
|
|
DialogWidget::~DialogWidget() = default;
|
|
|
|
DialogWidget& DialogWidget::operator=(DialogWidget&& other)
|
|
{
|
|
mp = std::move(other.mp);
|
|
return *this;
|
|
}
|
|
|
|
void DialogWidget::setDefaultAttr(const std::string& key, ValueHolder value)
|
|
{
|
|
mp->attrs.insert_or_assign(key, std::move(value));
|
|
}
|
|
|
|
ValueHolder DialogWidget::defaultAttr(const std::string& key) const
|
|
{
|
|
if (mp->attrs.find(key) == mp->attrs.end()) {
|
|
return ValueHolder();
|
|
}
|
|
else
|
|
return mp->attrs.at(key);
|
|
}
|
|
|
|
const std::string& DialogWidget::name() const
|
|
{
|
|
return mp->name;
|
|
}
|
|
|
|
DialogWidget::Type DialogWidget::type() const
|
|
{
|
|
return mp->type;
|
|
}
|
|
|
|
Scope& DialogWidget::addHook(const std::string& hookname, Scope&& scope)
|
|
{
|
|
mp->hooks.emplace(hookname, std::move(scope));
|
|
return mp->hooks.at(hookname);
|
|
}
|
|
|
|
std::optional<ScopeRef> DialogWidget::hook(const std::string& hookname) const
|
|
{
|
|
try {
|
|
return mp->hooks.at(hookname);
|
|
} catch (const std::out_of_range&) {
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
Dialog::~Dialog() = default;
|
|
|
|
Dialog::Dialog(const std::string& name)
|
|
: mp(new DialogPriv(name))
|
|
{}
|
|
|
|
Dialog::Dialog(Dialog&& other)
|
|
: mp(std::move(other.mp))
|
|
{}
|
|
|
|
Dialog& Dialog::operator=(Dialog&& other)
|
|
{
|
|
mp = std::move(other.mp);
|
|
return *this;
|
|
}
|
|
|
|
void Dialog::setDefaultAttr(const std::string& key, ValueHolder value)
|
|
{
|
|
mp->attrs.insert_or_assign(key, std::move(value));
|
|
}
|
|
|
|
ValueHolder Dialog::defaultAttr(const std::string& key) const
|
|
{
|
|
if (mp->attrs.find(key) == mp->attrs.end()) {
|
|
return ValueHolder();
|
|
}
|
|
else
|
|
return mp->attrs.at(key);
|
|
}
|
|
|
|
const std::string& Dialog::name() const
|
|
{
|
|
return mp->name;
|
|
}
|
|
|
|
DialogWidget& Dialog::addWidget(const std::string& name, DialogWidget::Type type)
|
|
{
|
|
if (mp->widgets.find(name) != mp->widgets.end())
|
|
throw ScriptException("Dialog widget of name '" + name + "' already exists");
|
|
mp->widgets.insert_or_assign(name, DialogWidget(name, type));
|
|
mp->widgetNames.emplace_back(name);
|
|
return mp->widgets.at(name);
|
|
}
|
|
|
|
DialogWidget& Dialog::widget(const std::string& name)
|
|
{
|
|
if (mp->widgets.find(name) == mp->widgets.end())
|
|
throw ScriptException("Dialog widget of name '" + name + "' does not exist");
|
|
return mp->widgets.at(name);
|
|
}
|
|
|
|
std::vector<DialogWidgetRef> Dialog::allWidgets() const
|
|
{
|
|
std::vector<DialogWidgetRef> ret;
|
|
for (auto widgetName : mp->widgetNames)
|
|
ret.emplace_back(mp->widgets.at(widgetName));
|
|
return ret;
|
|
}
|
|
|
|
Scope& Dialog::addHook(const std::string& hookname, Scope&& scope)
|
|
{
|
|
mp->hooks.emplace(hookname, std::move(scope));
|
|
return mp->hooks.at(hookname);
|
|
}
|
|
|
|
std::optional<ScopeRef> Dialog::hook(const std::string& hookname) const
|
|
{
|
|
try {
|
|
return mp->hooks.at(hookname);
|
|
} catch (const std::out_of_range&) {
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|