1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Use kind-of-factory approach for widget builders

This commit is contained in:
nordsoft 2022-12-22 02:05:29 +04:00
parent 8f7025328f
commit e245dbaf9d
4 changed files with 34 additions and 62 deletions

View File

@ -35,6 +35,21 @@ InterfaceObjectConfigurable::InterfaceObjectConfigurable(const JsonNode & config
InterfaceObjectConfigurable::InterfaceObjectConfigurable(int used, Point offset): InterfaceObjectConfigurable::InterfaceObjectConfigurable(int used, Point offset):
CIntObject(used, offset) CIntObject(used, offset)
{ {
REGISTER_BUILDER("picture", &InterfaceObjectConfigurable::buildPicture);
REGISTER_BUILDER("image", &InterfaceObjectConfigurable::buildImage);
REGISTER_BUILDER("texture", &InterfaceObjectConfigurable::buildTexture);
REGISTER_BUILDER("animation", &InterfaceObjectConfigurable::buildAnimation);
REGISTER_BUILDER("label", &InterfaceObjectConfigurable::buildLabel);
REGISTER_BUILDER("toggleGroup", &InterfaceObjectConfigurable::buildToggleGroup);
REGISTER_BUILDER("toggleButton", &InterfaceObjectConfigurable::buildToggleButton);
REGISTER_BUILDER("button", &InterfaceObjectConfigurable::buildButton);
REGISTER_BUILDER("labelGroup", &InterfaceObjectConfigurable::buildLabelGroup);
REGISTER_BUILDER("slider", &InterfaceObjectConfigurable::buildSlider);
}
void InterfaceObjectConfigurable::registerBuilder(const std::string & type, BuilderFunction f)
{
builders[type] = f;
} }
void InterfaceObjectConfigurable::addCallback(const std::string & callbackName, std::function<void(int)> callback) void InterfaceObjectConfigurable::addCallback(const std::string & callbackName, std::function<void(int)> callback)
@ -365,53 +380,10 @@ std::shared_ptr<CIntObject> InterfaceObjectConfigurable::buildWidget(JsonNode co
} }
auto type = config["type"].String(); auto type = config["type"].String();
if(type == "picture") auto buildIterator = builders.find(type);
{ if(buildIterator != builders.end())
return buildPicture(config); return (buildIterator->second)(config);
}
if(type == "image")
{
return buildImage(config);
}
if(type == "texture")
{
return buildTexture(config);
}
if(type == "animation")
{
return buildAnimation(config);
}
if(type == "label")
{
return buildLabel(config);
}
if(type == "toggleGroup")
{
return buildToggleGroup(config);
}
if(type == "toggleButton")
{
return buildToggleButton(config);
}
if(type == "button")
{
return buildButton(config);
}
if(type == "labelGroup")
{
return buildLabelGroup(config);
}
if(type == "slider")
{
return buildSlider(config);
}
logGlobal->debug("Calling custom widget building function"); logGlobal->error("Builder with type %s is not registered", type);
return const_cast<InterfaceObjectConfigurable*>(this)->buildCustomWidget(config);
}
std::shared_ptr<CIntObject> InterfaceObjectConfigurable::buildCustomWidget(const JsonNode & config)
{
logGlobal->error("Default custom widget builder called");
return nullptr; return nullptr;
} }

View File

@ -25,6 +25,8 @@ class CAnimImage;
class CShowableAnim; class CShowableAnim;
class CFilledTexture; class CFilledTexture;
#define REGISTER_BUILDER(type, method) registerBuilder(type, std::bind(method, this, std::placeholders::_1))
class InterfaceObjectConfigurable: public CIntObject class InterfaceObjectConfigurable: public CIntObject
{ {
public: public:
@ -32,6 +34,10 @@ public:
InterfaceObjectConfigurable(const JsonNode & config, int used=0, Point offset=Point()); InterfaceObjectConfigurable(const JsonNode & config, int used=0, Point offset=Point());
protected: protected:
using BuilderFunction = std::function<std::shared_ptr<CIntObject>(const JsonNode &)>;
void registerBuilder(const std::string &, BuilderFunction);
//must be called after adding callbacks //must be called after adding callbacks
void init(const JsonNode & config); void init(const JsonNode & config);
@ -67,14 +73,13 @@ protected:
std::shared_ptr<CAnimImage> buildImage(const JsonNode &) const; std::shared_ptr<CAnimImage> buildImage(const JsonNode &) const;
std::shared_ptr<CShowableAnim> buildAnimation(const JsonNode &) const; std::shared_ptr<CShowableAnim> buildAnimation(const JsonNode &) const;
std::shared_ptr<CFilledTexture> buildTexture(const JsonNode &) const; std::shared_ptr<CFilledTexture> buildTexture(const JsonNode &) const;
//composite widgets //composite widgets
virtual std::shared_ptr<CIntObject> buildCustomWidget(const JsonNode & config);
std::shared_ptr<CIntObject> buildWidget(JsonNode config) const; std::shared_ptr<CIntObject> buildWidget(JsonNode config) const;
private: private:
std::map<std::string, BuilderFunction> builders;
std::map<std::string, std::shared_ptr<CIntObject>> widgets; std::map<std::string, std::shared_ptr<CIntObject>> widgets;
std::map<std::string, std::function<void(int)>> callbacks; std::map<std::string, std::function<void(int)>> callbacks;
}; };

View File

@ -399,6 +399,8 @@ TemplatesDropBox::TemplatesDropBox(RandomMapTab & randomMapTab, int3 size):
InterfaceObjectConfigurable(LCLICK | HOVER), InterfaceObjectConfigurable(LCLICK | HOVER),
randomMapTab(randomMapTab) randomMapTab(randomMapTab)
{ {
REGISTER_BUILDER("templateListItem", &TemplatesDropBox::buildListItem);
curItems = VLC->tplh->getTemplates(); curItems = VLC->tplh->getTemplates();
vstd::erase_if(curItems, [size](const CRmgTemplate * t){return !t->matchesSize(size);}); vstd::erase_if(curItems, [size](const CRmgTemplate * t){return !t->matchesSize(size);});
curItems.insert(curItems.begin(), nullptr); //default template curItems.insert(curItems.begin(), nullptr); //default template
@ -422,16 +424,11 @@ TemplatesDropBox::TemplatesDropBox(RandomMapTab & randomMapTab, int3 size):
updateListItems(); updateListItems();
} }
std::shared_ptr<CIntObject> TemplatesDropBox::buildCustomWidget(const JsonNode & config) std::shared_ptr<CIntObject> TemplatesDropBox::buildListItem(const JsonNode & config)
{ {
if(config["type"].String() == "templateListItem") auto position = readPosition(config["position"]);
{ listItems.push_back(std::make_shared<ListItem>(config, *this, position));
auto position = readPosition(config["position"]); return listItems.back();
listItems.push_back(std::make_shared<ListItem>(config, *this, position));
return listItems.back();
}
return InterfaceObjectConfigurable::buildCustomWidget(config);
} }
void TemplatesDropBox::sliderMove(int slidPos) void TemplatesDropBox::sliderMove(int slidPos)

View File

@ -72,10 +72,8 @@ public:
void clickLeft(tribool down, bool previousState) override; void clickLeft(tribool down, bool previousState) override;
void setTemplate(const CRmgTemplate *); void setTemplate(const CRmgTemplate *);
protected:
std::shared_ptr<CIntObject> buildCustomWidget(const JsonNode & config) override;
private: private:
std::shared_ptr<CIntObject> buildListItem(const JsonNode & config);
void sliderMove(int slidPos); void sliderMove(int slidPos);
void updateListItems(); void updateListItems();