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 120a6e
class Setter : 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 120a6e
class PropertyWriter : 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; }