MegaGlest/source/configurator/configuration.cpp

442 lines
11 KiB
C++

#include "configuration.h"
#include <stdexcept>
#include "xml_parser.h"
#include "util.h"
#include "conversion.h"
using namespace std;
using namespace Shared::Xml;
namespace Configurator{
// ===============================================
// class Configuration
// ===============================================
Configuration::~Configuration(){
for(unsigned int i= 0; i<fieldGroups.size(); ++i){
delete fieldGroups[i];
}
}
void Configuration::load(const string &path){
if(fileExists(path) == false) {
throw runtime_error("Cannot find file: " + path);
}
loadStructure(path);
if(fileExists(fileNameMain) == false) {
throw runtime_error("Cannot find file: " + fileNameMain);
}
loadValues(fileNameMain);
if(fileExists(fileName) == true) {
// throw runtime_error("Cannot find file: " + fileName);
loadValues(fileName,false);
}
}
void Configuration::loadStructure(const string &path){
XmlTree xmlTree;
xmlTree.load(path);
const XmlNode *configurationNode= xmlTree.getRootNode();
//title
title= configurationNode->getChild("title")->getAttribute("value")->getValue();
//fileNameMain
fileNameMain= configurationNode->getChild("file-name-main")->getAttribute("value")->getValue();
Properties::applyTagsToValue(fileNameMain);
//fileName
fileName= configurationNode->getChild("file-name")->getAttribute("value")->getValue();
Properties::applyTagsToValue(fileName);
//icon
XmlNode *iconNode= configurationNode->getChild("icon");
icon= iconNode->getAttribute("value")->getBoolValue();
if(icon) {
iconPath= iconNode->getAttribute("path")->getValue();
Properties::applyTagsToValue(iconPath);
}
const XmlNode *fieldGroupsNode= configurationNode->getChild("field-groups");
fieldGroups.resize(fieldGroupsNode->getChildCount());
for(unsigned int i=0; i<fieldGroups.size(); ++i){
const XmlNode *fieldGroupNode= fieldGroupsNode->getChild("field-group", i);
FieldGroup *fieldGroup= new FieldGroup();
fieldGroup->load(fieldGroupNode);
fieldGroups[i]= fieldGroup;
}
}
void Configuration::loadValues(const string &path,bool clearCurrentProperties) {
//printf("\nLoading [%s] clearCurrentProperties = %d\n",path.c_str(),clearCurrentProperties);
//Properties properties;
properties.load(path,clearCurrentProperties);
for(unsigned int i=0; i<fieldGroups.size(); ++i){
FieldGroup *fg= fieldGroups[i];
for(unsigned int j=0; j<fg->getFieldCount(); ++j){
Field *f= fg->getField(j);
f->setValue(properties.getString(f->getVariableName(),""));
}
}
}
void Configuration::save() {
//Properties properties;
//properties.load(fileNameMain);
//if(fileExists(fileName) == true) {
// properties.load(fileName,false);
//}
for(unsigned int i=0; i<fieldGroups.size(); ++i){
FieldGroup *fg= fieldGroups[i];
for(unsigned int j=0; j<fg->getFieldCount(); ++j){
Field *f= fg->getField(j);
f->updateValue();
if(!f->isValueValid(f->getValue())){
f->setValue(f->getDefaultValue());
f->updateControl();
}
properties.setString(f->getVariableName(), f->getValue());
}
}
properties.save(fileName);
}
string Field::getInfo() const{
return name+" (default: " + defaultValue + ")";
}
// ===============================================
// class FieldGroup
// ===============================================
FieldGroup::~FieldGroup(){
for(unsigned int i= 0; i<fields.size(); ++i){
delete fields[i];
}
}
void FieldGroup::load(const XmlNode *groupNode){
name= groupNode->getAttribute("name")->getValue();
fields.resize(groupNode->getChildCount());
for(unsigned int i=0; i<fields.size(); ++i){
const XmlNode *fieldNode= groupNode->getChild("field", i);
Field *f= newField(fieldNode->getAttribute("type")->getValue());
//name
const XmlNode *nameNode= fieldNode->getChild("name");
f->setName(nameNode->getAttribute("value")->getValue());
//variableName
const XmlNode *variableNameNode= fieldNode->getChild("variable-name");
f->setVariableName(variableNameNode->getAttribute("value")->getValue());
//description
const XmlNode *descriptionNode= fieldNode->getChild("description");
f->setDescription(descriptionNode->getAttribute("value")->getValue());
//default
const XmlNode *defaultNode= fieldNode->getChild("default");
f->setDefaultValue(defaultNode->getAttribute("value")->getValue());
f->loadSpecific(fieldNode);
if(!f->isValueValid(f->getDefaultValue())){
throw runtime_error("Default value not valid in field: " + f->getName() + " [" + f->getDefaultValue() + "]");
}
fields[i]= f;
}
}
Field *FieldGroup::newField(const string &type){
if(type=="Bool"){
return new BoolField();
}
else if(type=="Int"){
return new IntField();
}
else if(type=="Float"){
return new FloatField();
}
else if(type=="String"){
return new StringField();
}
else if(type=="Enum"){
return new EnumField();
}
else if(type=="IntRange"){
return new IntRangeField();
}
else if(type=="FloatRange"){
return new FloatRangeField();
}
else{
throw runtime_error("Unknown field type: " + type);
}
}
// ===============================================
// class BoolField
// ===============================================
void BoolField::createControl(wxWindow *parent, wxSizer *sizer){
checkBox= new wxCheckBox(parent, -1, Configuration::ToUnicode(""));
checkBox->SetValue(strToBool(value));
sizer->Add(checkBox);
}
void BoolField::updateValue(){
value= boolToStr(checkBox->GetValue());
}
void BoolField::updateControl(){
checkBox->SetValue(strToBool(value));
}
bool BoolField::isValueValid(const string &value){
try{
strToBool(value);
}
catch(const exception &){
return false;
}
return true;
}
// ===============================================
// class IntField
// ===============================================
void IntField::createControl(wxWindow *parent, wxSizer *sizer){
textCtrl= new wxTextCtrl(parent, -1, Configuration::ToUnicode(value.c_str()));
sizer->Add(textCtrl);
}
void IntField::updateValue(){
#if defined(__MINGW32__)
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(textCtrl->GetValue()));
value = tmp_buf;
#else
value= (const char*)wxFNCONV(textCtrl->GetValue());
#endif
}
void IntField::updateControl(){
textCtrl->SetValue(Configuration::ToUnicode(value.c_str()));
}
bool IntField::isValueValid(const string &value){
try{
strToInt(value);
}
catch(const exception &){
return false;
}
return true;
}
// ===============================================
// class FloatField
// ===============================================
void FloatField::createControl(wxWindow *parent, wxSizer *sizer){
textCtrl= new wxTextCtrl(parent, -1, Configuration::ToUnicode(value.c_str()));
sizer->Add(textCtrl);
}
void FloatField::updateValue(){
#if defined(__MINGW32__)
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(textCtrl->GetValue()));
value = tmp_buf;
#else
value= (const char*)wxFNCONV(textCtrl->GetValue());
#endif
}
void FloatField::updateControl(){
textCtrl->SetValue(Configuration::ToUnicode(value.c_str()));
}
bool FloatField::isValueValid(const string &value){
try{
strToFloat(value);
}
catch(const exception &){
return false;
}
return true;
}
// ===============================================
// class StringField
// ===============================================
void StringField::createControl(wxWindow *parent, wxSizer *sizer){
textCtrl= new wxTextCtrl(parent, -1, Configuration::ToUnicode(value.c_str()));
textCtrl->SetSize(wxSize(3*textCtrl->GetSize().x/2, textCtrl->GetSize().y));
sizer->Add(textCtrl);
}
void StringField::updateValue(){
#if defined(__MINGW32__)
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(textCtrl->GetValue()));
value = tmp_buf;
#else
value= (const char*)wxFNCONV(textCtrl->GetValue());
#endif
}
void StringField::updateControl(){
textCtrl->SetValue(Configuration::ToUnicode(value.c_str()));
}
bool StringField::isValueValid(const string &value){
return true;
}
// ===============================================
// class EnumField
// ===============================================
void EnumField::createControl(wxWindow *parent, wxSizer *sizer){
comboBox= new wxComboBox(parent, -1, Configuration::ToUnicode(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY);
for(unsigned int i=0; i<enumerants.size(); ++i){
comboBox->Append(Configuration::ToUnicode(enumerants[i].c_str()));
}
comboBox->SetValue(Configuration::ToUnicode(value.c_str()));
sizer->Add(comboBox);
}
void EnumField::updateValue(){
#if defined(__MINGW32__)
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(comboBox->GetValue()));
value = tmp_buf;
#else
value= (const char*)wxFNCONV(comboBox->GetValue());
#endif
}
void EnumField::updateControl(){
comboBox->SetValue(Configuration::ToUnicode(value.c_str()));
}
bool EnumField::isValueValid(const string &value){
return true;
}
void EnumField::loadSpecific(const XmlNode *fieldNode){
const XmlNode *enumsNode= fieldNode->getChild("enums");
for(unsigned int i=0; i<enumsNode->getChildCount(); ++i){
const XmlNode *enumNode= enumsNode->getChild("enum", i);
enumerants.push_back(enumNode->getAttribute("value")->getValue());
}
};
// ===============================================
// class IntRange
// ===============================================
void IntRangeField::createControl(wxWindow *parent, wxSizer *sizer){
slider= new wxSlider(parent, -1, strToInt(value), min, max, wxDefaultPosition, wxDefaultSize, wxSL_LABELS);
sizer->Add(slider);
}
void IntRangeField::updateValue(){
value= intToStr(slider->GetValue());
}
void IntRangeField::updateControl(){
slider->SetValue(strToInt(value));
}
bool IntRangeField::isValueValid(const string &value){
try{
strToInt(value);
}
catch(const exception &){
return false;
}
return true;
}
void IntRangeField::loadSpecific(const XmlNode *fieldNode){
const XmlNode *minNode= fieldNode->getChild("min");
min= strToInt(minNode->getAttribute("value")->getValue());
const XmlNode *maxNode= fieldNode->getChild("max");
max= strToInt(maxNode->getAttribute("value")->getValue());
}
string IntRangeField::getInfo() const{
return name + " (min: " + intToStr(min)+ ", max: " + intToStr(max) + ", default: " + defaultValue + ")";
}
// ===============================================
// class FloatRangeField
// ===============================================
void FloatRangeField::createControl(wxWindow *parent, wxSizer *sizer){
textCtrl= new wxTextCtrl(parent, -1, Configuration::ToUnicode(value.c_str()));
sizer->Add(textCtrl);
}
void FloatRangeField::updateValue(){
#if defined(__MINGW32__)
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(textCtrl->GetValue()));
value = tmp_buf;
#else
value= (const char*)wxFNCONV(textCtrl->GetValue());
#endif
}
void FloatRangeField::updateControl(){
textCtrl->SetValue(Configuration::ToUnicode(value.c_str()));
}
bool FloatRangeField::isValueValid(const string &value){
try{
float f= strToFloat(value);
return f>=min && f<=max;
}
catch(const exception &){
return false;
}
return true;
}
void FloatRangeField::loadSpecific(const XmlNode *fieldNode){
const XmlNode *minNode= fieldNode->getChild("min");
min= strToFloat(minNode->getAttribute("value")->getValue());
const XmlNode *maxNode= fieldNode->getChild("max");
max= strToFloat(maxNode->getAttribute("value")->getValue());
};
string FloatRangeField::getInfo() const{
return name + " (min: " + floatToStr(min)+ ", max: " + floatToStr(max) + ", default: " + defaultValue + ")";
}
}//end namespace