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