1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Interface builder refactored

This commit is contained in:
nordsoft 2022-12-16 00:46:36 +04:00
parent 2fe951f819
commit 2371e3e9a2
4 changed files with 265 additions and 127 deletions

View File

@ -57,7 +57,7 @@ void InterfaceObjectConfigurable::init(const JsonNode &config)
}
}
std::string InterfaceObjectConfigurable::buildText(const JsonNode & config) const
std::string InterfaceObjectConfigurable::readText(const JsonNode & config) const
{
if(config.isNull())
return "";
@ -69,145 +69,207 @@ std::string InterfaceObjectConfigurable::buildText(const JsonNode & config) cons
return config.String();
}
std::shared_ptr<CIntObject> InterfaceObjectConfigurable::buildWidget(const JsonNode & config)
Point InterfaceObjectConfigurable::readPosition(const JsonNode & config) const
{
Point p;
p.x = config["x"].Integer();
p.y = config["y"].Integer();
return p;
}
ETextAlignment InterfaceObjectConfigurable::readTextAlignment(const JsonNode & config) const
{
if(!config.isNull())
{
if(config.String() == "center")
return ETextAlignment::CENTER;
if(config.String() == "left")
return ETextAlignment::TOPLEFT;
if(config.String() == "right")
return ETextAlignment::BOTTOMRIGHT;
}
return ETextAlignment::CENTER;
}
SDL_Color InterfaceObjectConfigurable::readColor(const JsonNode & config) const
{
if(!config.isNull())
{
if(config.String() == "yellow")
return Colors::YELLOW;
if(config.String() == "white")
return Colors::WHITE;
if(config.String() == "gold")
return Colors::METALLIC_GOLD;
if(config.String() == "green")
return Colors::GREEN;
if(config.String() == "orange")
return Colors::ORANGE;
if(config.String() == "bright-yellow")
return Colors::BRIGHT_YELLOW;
}
return Colors::DEFAULT_KEY_COLOR;
}
EFonts InterfaceObjectConfigurable::readFont(const JsonNode & config) const
{
if(!config.isNull())
{
if(config.String() == "big")
return EFonts::FONT_BIG;
if(config.String() == "medium")
return EFonts::FONT_MEDIUM;
if(config.String() == "small")
return EFonts::FONT_SMALL;
if(config.String() == "tiny")
return EFonts::FONT_TINY;
}
return EFonts::FONT_TIMES;
}
std::pair<std::string, std::string> InterfaceObjectConfigurable::readHintText(const JsonNode & config) const
{
std::pair<std::string, std::string> result;
if(!config.isNull())
{
if(config.isNumber())
return CGI->generaltexth->zelp[config.Integer()];
if(config.getType() == JsonNode::JsonType::DATA_STRUCT)
{
result.first = config["hover"].String();
result.second = config["help"].String();
return result;
}
if(config.getType() == JsonNode::JsonType::DATA_STRING)
{
result.first = result.second = config.String();
}
}
return result;
}
std::shared_ptr<CPicture> InterfaceObjectConfigurable::buildPicture(const JsonNode & config) const
{
auto image = readText(config["image"]);
auto position = readPosition(config["position"]);
return std::make_shared<CPicture>(image, position.x, position.y);
}
std::shared_ptr<CLabel> InterfaceObjectConfigurable::buildLabel(const JsonNode & config) const
{
auto font = readFont(config["font"]);
auto alignment = readTextAlignment(config["alignment"]);
auto color = readColor(config["color"]);
auto text = readText(config["text"]);
auto position = readPosition(config["position"]);
return std::make_shared<CLabel>(position.x, position.y, font, alignment, color, text);
}
std::shared_ptr<CToggleGroup> InterfaceObjectConfigurable::buildToggleGroup(const JsonNode & config) const
{
auto position = readPosition(config["position"]);
auto group = std::make_shared<CToggleGroup>(0);
group->pos += position;
if(!config["items"].isNull())
{
SObjectConstruction obj__i(group.get());
int itemIdx = -1;
for(const auto & item : config["items"].Vector())
{
itemIdx = item["index"].isNull() ? itemIdx + 1 : item["index"].Integer();
group->addToggle(itemIdx, std::dynamic_pointer_cast<CToggleBase>(buildWidget(item)));
}
}
if(!config["selected"].isNull())
group->setSelected(config["selected"].Integer());
if(!config["callback"].isNull())
group->addCallback(callbacks.at(config["callback"].String()));
return group;
}
std::shared_ptr<CToggleButton> InterfaceObjectConfigurable::buildToggleButton(const JsonNode & config) const
{
auto position = readPosition(config["position"]);
auto image = config["image"].String();
auto zelp = readHintText(config["zelp"]);
auto button = std::make_shared<CToggleButton>(position, image, zelp);
if(!config["selected"].isNull())
button->setSelected(config["selected"].Bool());
if(!config["imageOrder"].isNull())
{
auto imgOrder = config["imageOrder"].Vector();
assert(imgOrder.size() >= 4);
button->setImageOrder(imgOrder[0].Integer(), imgOrder[1].Integer(), imgOrder[2].Integer(), imgOrder[3].Integer());
}
if(!config["callback"].isNull())
button->addCallback(callbacks.at(config["callback"].String()));
return button;
}
std::shared_ptr<CButton> InterfaceObjectConfigurable::buildButton(const JsonNode & config) const
{
auto position = readPosition(config["position"]);
auto image = config["image"].String();
auto zelp = readHintText(config["zelp"]);
auto button = std::make_shared<CButton>(position, image, zelp);
if(!config["items"].isNull())
{
for(const auto & item : config["items"].Vector())
{
button->addOverlay(buildWidget(item));
}
}
if(!config["callback"].isNull())
button->addCallback(std::bind(callbacks.at(config["callback"].String()), 0));
return button;
}
std::shared_ptr<CLabelGroup> InterfaceObjectConfigurable::buildLabelGroup(const JsonNode & config) const
{
auto font = readFont(config["font"]);
auto alignment = readTextAlignment(config["alignment"]);
auto color = readColor(config["color"]);
auto group = std::make_shared<CLabelGroup>(font, alignment, color);
if(!config["items"].isNull())
{
for(const auto & item : config["items"].Vector())
{
auto position = readPosition(item["position"]);
auto text = readText(item["text"]);
group->add(position.x, position.y, text);
}
}
return group;
}
std::shared_ptr<CIntObject> InterfaceObjectConfigurable::buildWidget(const JsonNode & config) const
{
assert(!config.isNull());
auto type = config["type"].String();
int x = 0, y = 0;
if(!config["position"].isNull())
{
x = config["position"]["x"].Integer();
y = config["position"]["y"].Integer();
}
std::string image;
std::string text = buildText(config["text"]);
auto alignment = EAlignment::CENTER;
auto color = Colors::DEFAULT_KEY_COLOR;
auto font = EFonts::FONT_TIMES;
if(!config["image"].isNull())
image = config["image"].String();
if(!config["alignment"].isNull())
{
if(config["alignment"].String() == "left")
alignment = EAlignment::TOPLEFT;
if(config["alignment"].String() == "center")
alignment = EAlignment::CENTER;
if(config["alignment"].String() == "right")
alignment = EAlignment::BOTTOMRIGHT;
}
if(!config["color"].isNull())
{
if(config["color"].String() == "yellow")
color = Colors::YELLOW;
if(config["color"].String() == "white")
color = Colors::WHITE;
if(config["color"].String() == "gold")
color = Colors::METALLIC_GOLD;
if(config["color"].String() == "green")
color = Colors::GREEN;
if(config["color"].String() == "orange")
color = Colors::ORANGE;
if(config["color"].String() == "bright-yellow")
color = Colors::BRIGHT_YELLOW;
}
if(!config["font"].isNull())
{
if(config["font"].String() == "big")
font = EFonts::FONT_BIG;
if(config["font"].String() == "medium")
font = EFonts::FONT_MEDIUM;
if(config["font"].String() == "small")
font = EFonts::FONT_SMALL;
if(config["font"].String() == "tiny")
font = EFonts::FONT_TINY;
}
if(type == "picture")
{
return std::make_shared<CPicture>(image, x, y);
return buildPicture(config);
}
if(type == "label")
{
return std::make_shared<CLabel>(x, y, font, alignment, color, text);
return buildLabel(config);
}
if(type == "toggleGroup")
{
auto group = std::make_shared<CToggleGroup>(0);
group->pos.x += x;
group->pos.y += y;
if(!config["items"].isNull())
{
SObjectConstruction obj__i(group.get());
int itemIdx = -1;
for(const auto & item : config["items"].Vector())
{
itemIdx = item["index"].isNull() ? itemIdx + 1 : item["index"].Integer();
group->addToggle(itemIdx, std::dynamic_pointer_cast<CToggleBase>(buildWidget(item)));
}
}
if(!config["selected"].isNull())
group->setSelected(config["selected"].Integer());
if(!config["callback"].isNull())
group->addCallback(callbacks[config["callback"].String()]);
return group;
return buildToggleGroup(config);
}
if(type == "toggleButton")
{
std::pair<std::string, std::string> zelp;
if(!config["zelp"].isNull())
zelp = CGI->generaltexth->zelp[config["zelp"].Integer()];
auto button = std::make_shared<CToggleButton>(Point(x, y), image, zelp);
if(!config["selected"].isNull())
button->setSelected(config["selected"].Bool());
if(!config["imageOrder"].isNull())
{
auto imgOrder = config["imageOrder"].Vector();
assert(imgOrder.size() >= 4);
button->setImageOrder(imgOrder[0].Integer(), imgOrder[1].Integer(), imgOrder[2].Integer(), imgOrder[3].Integer());
}
if(!config["callback"].isNull())
button->addCallback(callbacks[config["callback"].String()]);
return button;
return buildToggleButton(config);
}
if(type == "button")
{
std::pair<std::string, std::string> zelp;
if(!config["zelp"].isNull())
zelp = CGI->generaltexth->zelp[config["zelp"].Integer()];
auto button = std::make_shared<CButton>(Point(x, y), image, zelp);
if(!config["items"].isNull())
{
for(const auto & item : config["items"].Vector())
{
button->addOverlay(buildWidget(item));
}
}
if(!config["callback"].isNull())
button->addCallback(std::bind(callbacks[config["callback"].String()], 0));
return button;
return buildButton(config);
}
if(type == "labelGroup")
{
auto group = std::make_shared<CLabelGroup>(font, alignment, color);
if(!config["items"].isNull())
{
for(const auto & item : config["items"].Vector())
{
if(!item["position"].isNull())
{
x = item["position"]["x"].Integer();
y = item["position"]["y"].Integer();
}
if(!item["text"].isNull())
text = buildText(item["text"]);
group->add(x, y, text);
}
}
return group;
return buildLabelGroup(config);
}
return std::shared_ptr<CIntObject>(nullptr);
}

View File

@ -14,6 +14,13 @@
#include "../../lib/JsonNode.h"
class CPicture;
class CLabel;
class CToggleGroup;
class CToggleButton;
class CButton;
class CLabelGroup;
class InterfaceObjectConfigurable: public CIntObject
{
public:
@ -35,12 +42,29 @@ protected:
return std::dynamic_pointer_cast<T>(iter->second);
}
private: //field deserializers
//basic serializers
Point readPosition(const JsonNode &) const;
ETextAlignment readTextAlignment(const JsonNode &) const;
SDL_Color readColor(const JsonNode &) const;
EFonts readFont(const JsonNode &) const;
std::string readText(const JsonNode &) const;
std::pair<std::string, std::string> readHintText(const JsonNode &) const;
//basic widgets
std::shared_ptr<CPicture> buildPicture(const JsonNode &) const;
std::shared_ptr<CLabel> buildLabel(const JsonNode &) const;
std::shared_ptr<CToggleGroup> buildToggleGroup(const JsonNode &) const;
std::shared_ptr<CToggleButton> buildToggleButton(const JsonNode &) const;
std::shared_ptr<CButton> buildButton(const JsonNode &) const;
std::shared_ptr<CLabelGroup> buildLabelGroup(const JsonNode &) const;
std::shared_ptr<CIntObject> buildWidget(const JsonNode & config) const;
private:
std::map<std::string, std::shared_ptr<CIntObject>> widgets;
std::map<std::string, std::function<void(int)>> callbacks;
std::shared_ptr<CIntObject> buildWidget(const JsonNode & config);
std::string buildText(const JsonNode & param) const;
};

View File

@ -100,9 +100,23 @@ RandomMapTab::RandomMapTab():
//new callbacks available only from mod
addCallback("templateSelection", [&](int)
{
GH.pushInt(std::make_shared<TemplatesDropBox>(this, int3{mapGenOptions->getWidth(), mapGenOptions->getHeight(), 1 + mapGenOptions->getHasTwoLevels()}));
GH.pushIntT<TemplatesDropBox>(this, int3{mapGenOptions->getWidth(), mapGenOptions->getHeight(), 1 + mapGenOptions->getHasTwoLevels()});
});
addCallback("teamAlignments", [&](int)
{
GH.pushIntT<TeamAlignmentsWidget>(this);
});
for(auto road : VLC->terrainTypeHandler->roads())
{
std::string cbRoadType = "selectRoad_" + road.fileName;
addCallback(cbRoadType, [&](bool on)
{
//TODO: support road types
});
}
init(config);
@ -293,7 +307,7 @@ TemplatesDropBox::ListItem::ListItem(TemplatesDropBox * _dropBox, Point position
dropBox(_dropBox)
{
OBJ_CONSTRUCTION;
labelName = std::make_shared<CLabel>(0, 0, FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE);
labelName = std::make_shared<CLabel>(0, 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
labelName->setAutoRedraw(false);
hoverImage = std::make_shared<CPicture>("List10Sl", 0, 0);
@ -352,6 +366,9 @@ TemplatesDropBox::TemplatesDropBox(RandomMapTab * randomMapTab, int3 size):
curItems.insert(curItems.begin(), nullptr); //default template
OBJ_CONSTRUCTION;
pos = randomMapTab->pos.topLeft();
pos.w = randomMapTab->pos.w;
pos.h = randomMapTab->pos.h;
background = std::make_shared<CPicture>("List10Bk", 158, 76);
int positionsToShow = 10;
@ -362,7 +379,6 @@ TemplatesDropBox::TemplatesDropBox(RandomMapTab * randomMapTab, int3 size):
slider = std::make_shared<CSlider>(Point(212 + 158, 76), 252, std::bind(&TemplatesDropBox::sliderMove, this, _1), positionsToShow, (int)curItems.size(), 0, false, CSlider::BLUE);
updateListItems();
pos = background->pos;
}
void TemplatesDropBox::sliderMove(int slidPos)
@ -410,3 +426,24 @@ void TemplatesDropBox::setTemplate(const CRmgTemplate * tmpl)
assert(GH.topInt().get() == this);
GH.popInt(GH.topInt());
}
TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab * randomMapTab):
CIntObject(),
randomMapTab(randomMapTab)
{
OBJ_CONSTRUCTION;
pos.w = 300;
pos.h = 300;
background = std::make_shared<CFilledTexture>("Bl3DCvex", pos);
center(pos);
buttonOk = std::make_shared<CButton>(Point(43, 240), "MUBCHCK.DEF", CGI->generaltexth->zelp[560], [](){});
buttonCancel = std::make_shared<CButton>(Point(193, 240), "MUBCANC.DEF", CGI->generaltexth->zelp[561], [&]()
{
assert(GH.topInt().get() == this);
GH.popInt(GH.topInt());
}, SDLK_ESCAPE);
}

View File

@ -85,3 +85,18 @@ private:
std::vector<const CRmgTemplate *> curItems;
};
class TeamAlignmentsWidget: public CIntObject
{
public:
TeamAlignmentsWidget(RandomMapTab * randomMapTab);
private:
RandomMapTab * randomMapTab;
std::shared_ptr<CFilledTexture> background;
std::shared_ptr<CLabelGroup> labels;
std::shared_ptr<CButton> buttonOk, buttonCancel;
std::vector<std::shared_ptr<CToggleGroup>> teams;
};