|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tproperty.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstream.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "texception.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TProperty::addListener(Listener *listener) {
|
|
Shinya Kitaoka |
120a6e |
if (std::find(m_listeners.begin(), m_listeners.end(), listener) ==
|
|
Shinya Kitaoka |
120a6e |
m_listeners.end())
|
|
Shinya Kitaoka |
120a6e |
m_listeners.push_back(listener);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TProperty::removeListener(Listener *listener) {
|
|
Shinya Kitaoka |
120a6e |
m_listeners.erase(
|
|
Shinya Kitaoka |
120a6e |
std::remove(m_listeners.begin(), m_listeners.end(), listener),
|
|
Shinya Kitaoka |
120a6e |
m_listeners.end());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TProperty::notifyListeners() const {
|
|
Shinya Kitaoka |
120a6e |
std::vector<listener *="">::const_iterator it;</listener>
|
|
Shinya Kitaoka |
120a6e |
for (it = m_listeners.begin(); it != m_listeners.end(); ++it)
|
|
Shinya Kitaoka |
120a6e |
(*it)->onPropertyChanged();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPropertyGroup::TPropertyGroup() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPropertyGroup::~TPropertyGroup() {
|
|
Shinya Kitaoka |
120a6e |
for (PropertyVector::iterator it = m_properties.begin();
|
|
Shinya Kitaoka |
120a6e |
it != m_properties.end(); ++it)
|
|
Shinya Kitaoka |
120a6e |
if (it->second) delete it->first;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TPropertyGroup::clear() {
|
|
Shinya Kitaoka |
120a6e |
m_properties.clear();
|
|
Shinya Kitaoka |
120a6e |
m_table.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPropertyGroup *TPropertyGroup::clone() const {
|
|
Shinya Kitaoka |
120a6e |
TPropertyGroup *g = new TPropertyGroup();
|
|
Shinya Kitaoka |
120a6e |
for (PropertyVector::const_iterator i = m_properties.begin();
|
|
Shinya Kitaoka |
120a6e |
i != m_properties.end(); ++i)
|
|
Shinya Kitaoka |
120a6e |
g->add(i->first->clone());
|
|
Shinya Kitaoka |
120a6e |
return g;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TPropertyGroup::add(TProperty *p) {
|
|
Shinya Kitaoka |
120a6e |
std::string name = p->getName();
|
|
Shinya Kitaoka |
120a6e |
assert(m_table.find(name) == m_table.end());
|
|
Shinya Kitaoka |
120a6e |
m_properties.push_back(std::make_pair(p, true));
|
|
Shinya Kitaoka |
120a6e |
m_table[name] = p;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TPropertyGroup::bind(TProperty &p) {
|
|
Shinya Kitaoka |
120a6e |
std::string name = p.getName();
|
|
Shinya Kitaoka |
120a6e |
assert(m_table.find(name) == m_table.end());
|
|
Shinya Kitaoka |
120a6e |
m_properties.push_back(std::make_pair(&p, false));
|
|
Shinya Kitaoka |
120a6e |
m_table[name] = &p;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TProperty *TPropertyGroup::getProperty(std::string name) {
|
|
Shinya Kitaoka |
120a6e |
PropertyTable::iterator i = m_table.find(name);
|
|
Shinya Kitaoka |
120a6e |
if (i == m_table.end())
|
|
Shinya Kitaoka |
120a6e |
return 0;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return i->second;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <class property=""></class>
|
|
Shinya Kitaoka |
120a6e |
void assign(Property *dst, TProperty *src) {
|
|
Shinya Kitaoka |
120a6e |
Property *s = dynamic_cast<property *="">(src);</property>
|
|
Shinya Kitaoka |
120a6e |
if (!s) throw TProperty::TypeError();
|
|
Shinya Kitaoka |
120a6e |
dst->setValue(s->getValue());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class Setter final : public TProperty::Visitor {
|
|
Shinya Kitaoka |
120a6e |
TProperty *m_src;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
Setter(TProperty *src) : m_src(src) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void visit(TDoubleProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TIntProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TStringProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TBoolProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TEnumProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TDoublePairProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TIntPairProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TStyleIndexProperty *dst) override { assign(dst, m_src); }
|
|
Shinya Kitaoka |
473e70 |
void visit(TPointerProperty *dst) override { assign(dst, m_src); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TPropertyGroup::setProperties(TPropertyGroup *g) {
|
|
Shinya Kitaoka |
120a6e |
for (PropertyVector::const_iterator i = g->m_properties.begin();
|
|
Shinya Kitaoka |
120a6e |
i != g->m_properties.end(); ++i) {
|
|
Shinya Kitaoka |
120a6e |
TProperty *src = i->first;
|
|
Shinya Kitaoka |
120a6e |
TProperty *dst = getProperty(src->getName());
|
|
Shinya Kitaoka |
120a6e |
if (dst) {
|
|
Shinya Kitaoka |
120a6e |
Setter setter(src);
|
|
Shinya Kitaoka |
120a6e |
TProperty::Visitor *visitor = &setter;
|
|
Shinya Kitaoka |
120a6e |
dst->accept(*visitor);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TPropertyGroup::accept(TProperty::Visitor &v) {
|
|
Shinya Kitaoka |
120a6e |
for (PropertyVector::const_iterator i = m_properties.begin();
|
|
Shinya Kitaoka |
120a6e |
i != m_properties.end(); ++i)
|
|
Shinya Kitaoka |
120a6e |
i->first->accept(v);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
d1f6c4 |
class PropertyWriter final : public TProperty::Visitor {
|
|
Shinya Kitaoka |
120a6e |
TOStream &m_os;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
PropertyWriter(TOStream &os) : m_os(os) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void visit(TDoubleProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "double";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["min"] = std::to_string(p->getRange().first);
|
|
Shinya Kitaoka |
120a6e |
attr["max"] = std::to_string(p->getRange().second);
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = std::to_string(p->getValue());
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void visit(TDoublePairProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "pair";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["min"] = std::to_string(p->getRange().first);
|
|
Shinya Kitaoka |
120a6e |
attr["max"] = std::to_string(p->getRange().second);
|
|
Shinya Kitaoka |
120a6e |
TDoublePairProperty::Value value = p->getValue();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] =
|
|
Shinya Kitaoka |
120a6e |
std::to_string(value.first) + " " + std::to_string(value.second);
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void visit(TIntPairProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "pair";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["min"] = std::to_string(p->getRange().first);
|
|
Shinya Kitaoka |
120a6e |
attr["max"] = std::to_string(p->getRange().second);
|
|
Shinya Kitaoka |
120a6e |
TIntPairProperty::Value value = p->getValue();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] =
|
|
Shinya Kitaoka |
120a6e |
std::to_string(value.first) + " " + std::to_string(value.second);
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void visit(TIntProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "int";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["min"] = std::to_string(p->getRange().first);
|
|
Shinya Kitaoka |
120a6e |
attr["max"] = std::to_string(p->getRange().second);
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = std::to_string(p->getValue());
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void visit(TBoolProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "bool";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = p->getValue() ? "true" : "false";
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void visit(TStringProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "string";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = ::to_string(p->getValue());
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void visit(TStyleIndexProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "string";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = p->getValueAsString();
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void visit(TEnumProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "enum";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = ::to_string(p->getValue());
|
|
Shinya Kitaoka |
120a6e |
if (TEnumProperty::isRangeSavingEnabled()) {
|
|
Shinya Kitaoka |
120a6e |
m_os.openChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
std::vector<std::wstring> range = p->getRange();</std::wstring>
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)range.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
attr.clear();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = ::to_string(range[i]);
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("item", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_os.closeChild();
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
473e70 |
void visit(TPointerProperty *p) override {
|
|
Shinya Kitaoka |
120a6e |
std::map<std::string, std::string=""> attr;</std::string,>
|
|
Shinya Kitaoka |
120a6e |
attr["type"] = "pointer";
|
|
Shinya Kitaoka |
120a6e |
attr["name"] = p->getName();
|
|
Shinya Kitaoka |
120a6e |
attr["value"] = p->getValueAsString();
|
|
Shinya Kitaoka |
120a6e |
m_os.openCloseChild("property", attr);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TPropertyGroup::loadData(TIStream &is) {
|
|
Shinya Kitaoka |
120a6e |
for (PropertyVector::iterator it = m_properties.begin();
|
|
Shinya Kitaoka |
120a6e |
it != m_properties.end(); ++it)
|
|
Shinya Kitaoka |
120a6e |
if (it->second) delete it->first;
|
|
Shinya Kitaoka |
120a6e |
m_properties.clear();
|
|
Shinya Kitaoka |
120a6e |
m_table.clear();
|
|
Shinya Kitaoka |
120a6e |
std::string tagName;
|
|
Shinya Kitaoka |
120a6e |
while (is.matchTag(tagName)) {
|
|
Shinya Kitaoka |
120a6e |
if (tagName == "property") {
|
|
Shinya Kitaoka |
120a6e |
std::string name = is.getTagAttribute("name");
|
|
Shinya Kitaoka |
120a6e |
std::string type = is.getTagAttribute("type");
|
|
Shinya Kitaoka |
120a6e |
std::string svalue = is.getTagAttribute("value");
|
|
Shinya Kitaoka |
120a6e |
if (name == "") throw TException("missing property name");
|
|
Shinya Kitaoka |
120a6e |
if (type == "") throw TException("missing property type");
|
|
Shinya Kitaoka |
120a6e |
if (type != "string" && svalue == "")
|
|
Shinya Kitaoka |
120a6e |
throw TException("missing property value");
|
|
Shinya Kitaoka |
120a6e |
if (type == "double") {
|
|
Shinya Kitaoka |
120a6e |
double min = std::stod(is.getTagAttribute("min"));
|
|
Shinya Kitaoka |
120a6e |
double max = std::stod(is.getTagAttribute("max"));
|
|
Shinya Kitaoka |
120a6e |
add(new TDoubleProperty(name, min, max, std::stod(svalue)));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (type == "pair") {
|
|
Shinya Kitaoka |
120a6e |
double min = std::stod(is.getTagAttribute("min"));
|
|
Shinya Kitaoka |
120a6e |
double max = std::stod(is.getTagAttribute("max"));
|
|
Shinya Kitaoka |
120a6e |
TDoublePairProperty::Value v(0, 0);
|
|
Shinya Kitaoka |
120a6e |
int i = svalue.find(' ');
|
|
Shinya Kitaoka |
120a6e |
if (i != (int)std::string::npos) {
|
|
Shinya Kitaoka |
120a6e |
v.first = std::stod(svalue.substr(0, i));
|
|
Shinya Kitaoka |
120a6e |
v.second = std::stod(svalue.substr(i + 1));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
add(new TDoublePairProperty(name, min, max, v.first, v.second));
|
|
Shinya Kitaoka |
120a6e |
} else if (type == "int") {
|
|
Shinya Kitaoka |
120a6e |
int min = std::stoi(is.getTagAttribute("min"));
|
|
Shinya Kitaoka |
120a6e |
int max = std::stoi(is.getTagAttribute("max"));
|
|
Shinya Kitaoka |
120a6e |
add(new TIntProperty(name, min, max, std::stoi(svalue)));
|
|
Shinya Kitaoka |
120a6e |
} else if (type == "bool") {
|
|
Shinya Kitaoka |
120a6e |
if (svalue != "true" && svalue != "false")
|
|
Shinya Kitaoka |
120a6e |
throw TException("bad boolean property value");
|
|
Shinya Kitaoka |
120a6e |
add(new TBoolProperty(name, svalue == "true" ? true : false));
|
|
Shinya Kitaoka |
120a6e |
} else if (type == "string") {
|
|
Shinya Kitaoka |
120a6e |
add(new TStringProperty(name, ::to_wstring(svalue)));
|
|
Shinya Kitaoka |
120a6e |
} else if (type == "enum") {
|
|
Shinya Kitaoka |
120a6e |
TEnumProperty *p = new TEnumProperty(name);
|
|
Shinya Kitaoka |
120a6e |
if (is.isBeginEndTag())
|
|
Shinya Kitaoka |
120a6e |
p->addValue(::to_wstring(svalue));
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
while (is.matchTag(tagName)) {
|
|
Shinya Kitaoka |
120a6e |
if (tagName == "item") {
|
|
Shinya Kitaoka |
120a6e |
std::string item = is.getTagAttribute("value");
|
|
Shinya Kitaoka |
120a6e |
p->addValue(::to_wstring(item));
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
throw TException("expected range property <item>");</item>
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
is.closeChild();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
p->setValue(::to_wstring(svalue));
|
|
Shinya Kitaoka |
120a6e |
add(p);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
throw TException("unrecognized property type : " + type);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
throw TException("expected <property>");</property>
|
|
Shinya Kitaoka |
120a6e |
// is.closeChild();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TPropertyGroup::saveData(TOStream &os) const {
|
|
Shinya Kitaoka |
120a6e |
PropertyWriter writer(os);
|
|
Shinya Kitaoka |
120a6e |
const_cast<tpropertygroup *="">(this)->accept(writer);</tpropertygroup>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
bool EnumRangeSavingEnabled = true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TEnumProperty::enableRangeSaving(bool on) { EnumRangeSavingEnabled = on; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool TEnumProperty::isRangeSavingEnabled() { return EnumRangeSavingEnabled; }
|