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.
 
 
 
 
idealirc/Script/Dialog.cpp

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;
}
}