diff --git a/mk/linux/Jamfile b/mk/linux/Jamfile
new file mode 100644
index 000000000..f9cddf447
--- /dev/null
+++ b/mk/linux/Jamfile
@@ -0,0 +1,101 @@
+SubDir TOP ;
+
+UseAutoconf ;
+
+Package license.txt readme.txt ;
+
+#### Library ####
+SubDir TOP shared_lib sources ;
+
+LIB_DIRS =
+ platform/sdl
+ platform/posix
+ util
+ graphics
+ graphics/gl
+ sound
+ sound/openal
+ xml
+ glew
+ lua
+;
+LIB_INCLUDE_DIRS = ../include/$(LIB_DIRS) ;
+
+for i in $(LIB_DIRS) {
+ LIB_SOURCES += [ Wildcard $(i) : *.c *.cpp *.h ] ;
+}
+
+Library glestlib : $(LIB_SOURCES) ;
+ExternalLibs glestlib : SDL GL GLU XERCES VORBIS VORBISFILE OGG OPENAL LUA ;
+IncludeDir glestlib : $(LIB_INCLUDE_DIRS) ;
+
+#### Game ####
+SubDir TOP glest_game ;
+
+GLEST_DIRS =
+ .
+ ai
+ facilities
+ game
+ global
+ graphics
+ gui
+ main
+ menu
+ network
+ sound
+ type_instances
+ types
+ world
+;
+
+for i in $(GLEST_DIRS) {
+ GLEST_SOURCES += [ Wildcard $(i) : *.cpp *.h ] ;
+}
+
+Application glest.bin : $(GLEST_SOURCES) ;
+LinkWith glest.bin : glestlib ;
+ExternalLibs glest.bin : SDL GL GLU XERCES VORBIS VORBISFILE OGG OPENAL LUA ;
+IncludeDir glest.bin : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_DIRS) ;
+
+#### Editor ####
+if $(WX_AVAILABLE) = "yes" {
+ SubDir TOP glest_map_editor ;
+
+ GLEST_MAP_DIRS = . ;
+ for i in $(GLEST_DIRS) {
+ GLEST_MAP_SOURCES += [ Wildcard $(i) : *.cpp *.h ] ;
+ }
+
+ Application glest_editor : $(GLEST_MAP_SOURCES) ;
+ LinkWith glest_editor : glestlib ;
+ ExternalLibs glest_editor : SDL GL GLU XERCES VORBIS VORBISFILE OGG OPENAL WX ;
+ IncludeDir glest_editor : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_MAP_DIRS) ;
+}
+
+### Viewer ###
+ SubDir TOP g3d_viewer ;
+
+ GLEST_VIEWER_DIRS = . ;
+ for i in $(GLEST_DIRS) {
+ GLEST_VIEWER_SOURCES += [ Wildcard $(i) : *.cpp *.h ] ;
+ }
+
+ Application glest_g3dviewer : $(GLEST_VIEWER_SOURCES) ;
+ LinkWith glest_g3dviewer : glestlib ;
+ ExternalLibs glest_g3dviewer : SDL GL GLU WX ;
+ IncludeDir glest_g3dviewer : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_VIEWER_DIRS) ;
+
+### Configurator ###
+ SubDir TOP configurator ;
+
+ GLEST_CONFIG_DIRS = . ;
+ for i in $(GLEST_DIRS) {
+ GLEST_CONFIG_SOURCES += [ Wildcard $(i) : *.cpp *.h ] ;
+ }
+
+ Application glest_configurator : $(GLEST_CONFIG_SOURCES) ;
+ LinkWith glest_configurator : glestlib ;
+ ExternalLibs glest_configurator : SDL GL GLU XERCES WX ;
+ IncludeDir glest_configurator : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_CONFIG_DIRS) ;
+
diff --git a/mk/linux/configuration.xml b/mk/linux/configuration.xml
new file mode 100644
index 000000000..613a9fd9f
--- /dev/null
+++ b/mk/linux/configuration.xml
@@ -0,0 +1,368 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/configurator/configuration.cpp b/source/configurator/configuration.cpp
new file mode 100644
index 000000000..8c583bd0b
--- /dev/null
+++ b/source/configurator/configuration.cpp
@@ -0,0 +1,392 @@
+#include "configuration.h"
+
+#include
+
+#include "xml_parser.h"
+#include "util.h"
+#include "properties.h"
+#include "conversion.h"
+
+using namespace std;
+using namespace Shared::Xml;
+using namespace Shared::Util;
+
+namespace Configurator{
+
+// ===============================================
+// class Configuration
+// ===============================================
+
+
+Configuration::~Configuration(){
+ for(int i= 0; igetChild("title")->getAttribute("value")->getValue();
+
+ //fileName
+ fileName= configurationNode->getChild("file-name")->getAttribute("value")->getValue();
+
+ //icon
+ XmlNode *iconNode= configurationNode->getChild("icon");
+ icon= iconNode->getAttribute("value")->getBoolValue();
+ if(icon){
+ iconPath= iconNode->getAttribute("path")->getValue();
+ }
+
+ const XmlNode *fieldGroupsNode= configurationNode->getChild("field-groups");
+
+ fieldGroups.resize(fieldGroupsNode->getChildCount());
+
+ for(int i=0; igetChild("field-group", i);
+ FieldGroup *fieldGroup= new FieldGroup();
+ fieldGroup->load(fieldGroupNode);
+ fieldGroups[i]= fieldGroup;
+ }
+}
+
+void Configuration::loadValues(const string &path){
+ Properties properties;
+
+ properties.load(path);
+
+ for(int i=0; igetFieldCount(); ++j){
+ Field *f= fg->getField(j);
+ f->setValue(properties.getString(f->getVariableName()));
+ }
+ }
+}
+
+void Configuration::save(){
+ Properties properties;
+
+ properties.load(fileName);
+
+ for(int i=0; igetFieldCount(); ++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(int i= 0; igetAttribute("name")->getValue();
+
+ fields.resize(groupNode->getChildCount());
+ for(int i=0; igetChild("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());
+ }
+
+ 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(){
+ value= (const char*)wxFNCONV(textCtrl->GetValue());
+}
+
+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(){
+ value= (const char*)wxFNCONV(textCtrl->GetValue());
+}
+
+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(){
+ value= (const char*)wxFNCONV(textCtrl->GetValue());
+}
+
+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(int i=0; iAppend(Configuration::ToUnicode(enumerants[i].c_str()));
+ }
+ comboBox->SetValue(Configuration::ToUnicode(value.c_str()));
+ sizer->Add(comboBox);
+}
+
+void EnumField::updateValue(){
+ value= (const char*)wxFNCONV(comboBox->GetValue());
+}
+
+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(int i=0; igetChildCount(); ++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(){
+ value= (const char*)wxFNCONV(textCtrl->GetValue());
+}
+
+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
diff --git a/source/configurator/configuration.h b/source/configurator/configuration.h
new file mode 100644
index 000000000..60359d225
--- /dev/null
+++ b/source/configurator/configuration.h
@@ -0,0 +1,250 @@
+#ifndef _CONFIGURATOR_CONFIGURATION_H_
+#define _CONFIGURATOR_CONFIGURATION_H_
+
+#include
+#include
+
+#include
+
+#include "xml_parser.h"
+
+using std::string;
+using std::vector;
+
+using Shared::Xml::XmlNode;
+
+namespace Configurator{
+
+// ===============================================
+// class Global functions
+// ===============================================
+
+class Field;
+class FieldGroup;
+
+// ===============================
+// class Configuration
+// ===============================
+
+class Configuration{
+public:
+ typedef vector FieldGroups;
+
+private:
+ string title;
+ string fileName;
+ bool icon;
+ string iconPath;
+ FieldGroups fieldGroups;
+
+public:
+ ~Configuration();
+
+ void load(const string &path);
+
+ void loadStructure(const string &path);
+ void loadValues(const string &path);
+
+ void save();
+
+ const string &getTitle() const {return title;}
+ const string &getFileName() const {return fileName;}
+ bool getIcon() const {return icon;}
+ const string &getIconPath() const {return iconPath;}
+
+ int getFieldGroupCount() const {return fieldGroups.size();}
+ FieldGroup *getFieldGroup(int i) const {return fieldGroups[i];}
+
+ static wxString ToUnicode(const char* str) {
+ return wxString(str, wxConvUTF8);
+ }
+
+ static wxString ToUnicode(const string& str) {
+ return wxString(str.c_str(), wxConvUTF8);
+ }
+
+};
+
+// ===============================
+// class FieldGroup
+// ===============================
+
+class FieldGroup{
+public:
+ typedef vector Fields;
+
+private:
+ Fields fields;
+ string name;
+
+public:
+ ~FieldGroup();
+
+ int getFieldCount() const {return fields.size();}
+ Field *getField(int i) const {return fields[i];}
+ const string &getName() const {return name;}
+
+ void load(const XmlNode *groupNode);
+
+private:
+ Field *newField(const string &type);
+};
+
+// ===============================
+// class Field
+// ===============================
+
+class Field{
+protected:
+ string name;
+ string variableName;
+ string description;
+ string value;
+ string defaultValue;
+
+public:
+ virtual ~Field() {};
+
+ const string &getName() const {return name;}
+ const string &getVariableName() const {return variableName;}
+ const string &getDescription() const {return description;}
+ const string &getValue() const {return value;}
+ const string &getDefaultValue() const {return defaultValue;}
+
+ void setName(const string &name) {this->name= name;}
+ void setVariableName(const string &variableName) {this->variableName= variableName;}
+ void setDescription(const string &description) {this->description= description;}
+ void setValue(const string &value) {this->value= value;}
+ void setDefaultValue(const string &defaultValue) {this->defaultValue= defaultValue;}
+
+ virtual void loadSpecific(const XmlNode *fieldNode){};
+ virtual string getInfo() const;
+
+ virtual void createControl(wxWindow *parent, wxSizer *sizer)= 0;
+ virtual void updateValue()= 0;
+ virtual void updateControl()= 0;
+ virtual bool isValueValid(const string &value)= 0;
+};
+
+// ===============================
+// class BoolField
+// ===============================
+
+class BoolField: public Field{
+private:
+ wxCheckBox *checkBox;
+
+public:
+ virtual void createControl(wxWindow *parent, wxSizer *sizer);
+ virtual void updateValue();
+ virtual void updateControl();
+ virtual bool isValueValid(const string &value);
+};
+
+// ===============================
+// class IntField
+// ===============================
+
+class IntField: public Field{
+private:
+ wxTextCtrl *textCtrl;
+
+public:
+ virtual void createControl(wxWindow *parent, wxSizer *sizer);
+ virtual void updateValue();
+ virtual void updateControl();
+ virtual bool isValueValid(const string &value);
+};
+
+// ===============================
+// class FloatField
+// ===============================
+
+class FloatField: public Field{
+private:
+ wxTextCtrl *textCtrl;
+
+public:
+ virtual void createControl(wxWindow *parent, wxSizer *sizer);
+ virtual void updateValue();
+ virtual void updateControl();
+ virtual bool isValueValid(const string &value);
+};
+
+// ===============================
+// class StringField
+// ===============================
+
+class StringField: public Field{
+private:
+ wxTextCtrl *textCtrl;
+
+public:
+ virtual void createControl(wxWindow *parent, wxSizer *sizer);
+ virtual void updateValue();
+ virtual void updateControl();
+ virtual bool isValueValid(const string &value);
+};
+
+// ===============================
+// class EnumField
+// ===============================
+
+class EnumField: public Field{
+private:
+ wxComboBox *comboBox;
+ vector enumerants;
+
+public:
+ virtual void createControl(wxWindow *parent, wxSizer *sizer);
+ virtual void updateValue();
+ virtual void updateControl();
+ virtual bool isValueValid(const string &value);
+
+ virtual void loadSpecific(const XmlNode *fieldNode);
+};
+
+// ===============================
+// class IntRangeField
+// ===============================
+
+class IntRangeField: public Field{
+private:
+ wxSlider *slider;
+ int min;
+ int max;
+
+public:
+ virtual void createControl(wxWindow *parent, wxSizer *sizer);
+ virtual void updateValue();
+ virtual void updateControl();
+ virtual bool isValueValid(const string &value);
+
+ virtual void loadSpecific(const XmlNode *fieldNode);
+ virtual string getInfo() const;
+};
+
+// ===============================
+// class FloatRangeField
+// ===============================
+
+class FloatRangeField: public Field{
+private:
+ wxTextCtrl *textCtrl;
+ float min;
+ float max;
+
+public:
+ virtual void createControl(wxWindow *parent, wxSizer *sizer);
+ virtual void updateValue();
+ virtual void updateControl();
+ virtual bool isValueValid(const string &value);
+
+ virtual void loadSpecific(const XmlNode *fieldNode);
+ virtual string getInfo() const;
+};
+
+
+}//end namespace
+
+#endif
diff --git a/source/configurator/main.cpp b/source/configurator/main.cpp
new file mode 100644
index 000000000..940f9d688
--- /dev/null
+++ b/source/configurator/main.cpp
@@ -0,0 +1,210 @@
+#include "main.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+namespace Configurator{
+
+// ===============================================
+// class MainWindow
+// ===============================================
+
+
+const int MainWindow::margin= 10;
+const int MainWindow::panelMargin= 20;
+const int MainWindow::gridMarginHorizontal= 30;
+
+const string MainWindow::versionString= "v1.3.5-beta1";
+const string MainWindow::winHeader= "Mega-Glest config " + versionString + " - Built: " + __DATE__;
+
+MainWindow::MainWindow() :
+ wxFrame(
+ NULL, -1, Configuration::ToUnicode(winHeader),
+ wxDefaultPosition, wxSize(800, 600)){
+
+ SetExtraStyle(wxFRAME_EX_CONTEXTHELP);
+
+ configuration.load("configuration.xml");
+
+ //Create(NULL, -1, "", wxDefaultPosition, wxDefaultSize, wxCAPTION | wxSYSTEM_MENU);
+
+ SetTitle(Configuration::ToUnicode(("Configurator - " + configuration.getTitle() + " - Editing " + configuration.getFileName()).c_str()));
+
+ if(configuration.getIcon()){
+
+ printf("In [%s::%s] icon = [%s]\n",__FILE__,__FUNCTION__,configuration.getIconPath().c_str());
+
+ wxInitAllImageHandlers();
+ wxIcon icon;
+ icon.LoadFile(Configuration::ToUnicode(configuration.getIconPath().c_str()), wxBITMAP_TYPE_ICO);
+ SetIcon(icon);
+ }
+
+ notebook= new wxNotebook(this, -1);
+
+ wxSizer *mainSizer= new wxBoxSizer(wxVERTICAL);
+ wxSizer *topSizer= new wxBoxSizer(wxHORIZONTAL);
+ topSizer->Add(notebook, 0, wxALL, 0);
+ mainSizer->Add(topSizer, 0, wxALL, margin);
+
+ for(int i=0; iAddPage(panel, Configuration::ToUnicode(fg->getName().c_str()));
+
+ //sizers
+ wxSizer *gridSizer= new wxFlexGridSizer(2, margin, gridMarginHorizontal);
+ wxSizer *panelSizer= new wxBoxSizer(wxVERTICAL);
+ panelSizer->Add(gridSizer, 0, wxALL, panelMargin);
+ panel->SetSizer(panelSizer);
+
+ for(int j=0; jgetFieldCount(); ++j){
+ Field *f= fg->getField(j);
+ FieldText *staticText= new FieldText(panel, this, f);
+ staticText->SetAutoLayout(true);
+ gridSizer->Add(staticText);
+ f->createControl(panel, gridSizer);
+ idMap.insert(IdPair(staticText->GetId(), staticText));
+ }
+ }
+
+ //buttons
+ wxSizer *bottomSizer= new wxBoxSizer(wxHORIZONTAL);
+
+ buttonOk= new wxButton(this, biOk, wxT("OK"));
+ buttonApply= new wxButton(this, biApply, wxT("Apply"));
+ buttonCancel= new wxButton(this, biCancel, wxT("Cancel"));
+ buttonDefault= new wxButton(this, biDefault, wxT("Default"));
+ bottomSizer->Add(buttonOk, 0, wxALL, margin);
+ bottomSizer->Add(buttonApply, 0, wxRIGHT | wxDOWN | wxUP, margin);
+ bottomSizer->Add(buttonCancel, 0, wxRIGHT | wxDOWN | wxUP, margin);
+ bottomSizer->Add(buttonDefault, 0, wxRIGHT | wxDOWN | wxUP, margin);
+
+ infoText= new wxTextCtrl(this, -1, Configuration::ToUnicode("Info text."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
+ infoText->SetSize(infoText->GetSize().x, 2*infoText->GetSize().y/3);
+ infoText->SetBackgroundColour(buttonOk->GetBackgroundColour());
+
+ mainSizer->Add(infoText, 1, wxGROW | wxALL | wxALIGN_CENTER, margin);
+ mainSizer->Add(bottomSizer, 0, wxALIGN_CENTER);
+
+ SetBackgroundColour(buttonOk->GetBackgroundColour());
+
+ SetSizerAndFit(mainSizer);
+
+ Refresh();
+}
+
+void MainWindow::init(){
+}
+
+void MainWindow::onButtonOk(wxCommandEvent &event){
+ configuration.save();
+ Close();
+}
+
+void MainWindow::onButtonApply(wxCommandEvent &event){
+ configuration.save();
+}
+
+void MainWindow::onButtonCancel(wxCommandEvent &event){
+ Close();
+}
+
+void MainWindow::onButtonDefault(wxCommandEvent &event){
+ for(int i=0; igetFieldCount(); ++j){
+ Field *f= fg->getField(j);
+ f->setValue(f->getDefaultValue());
+ f->updateControl();
+ }
+ }
+}
+
+void MainWindow::onClose(wxCloseEvent &event){
+ Destroy();
+}
+
+void MainWindow::onMouseDown(wxMouseEvent &event){
+ setInfoText("");
+}
+
+void MainWindow::setInfoText(const string &str){
+ infoText->SetValue(Configuration::ToUnicode(str.c_str()));
+}
+
+BEGIN_EVENT_TABLE(MainWindow, wxFrame)
+ EVT_BUTTON(biOk, MainWindow::onButtonOk)
+ EVT_BUTTON(biApply, MainWindow::onButtonApply)
+ EVT_BUTTON(biCancel, MainWindow::onButtonCancel)
+ EVT_BUTTON(biDefault, MainWindow::onButtonDefault)
+ EVT_CLOSE(MainWindow::onClose)
+ EVT_LEFT_DOWN(MainWindow::onMouseDown)
+END_EVENT_TABLE()
+
+// ===============================================
+// class FieldText
+// ===============================================
+
+FieldText::FieldText(wxWindow *parent, MainWindow *mainWindow, const Field *field):
+ wxStaticText(parent, -1, Configuration::ToUnicode(field->getName().c_str()))
+{
+ this->mainWindow= mainWindow;
+ this->field= field;
+}
+
+void FieldText::onHelp(wxHelpEvent &event){
+ string str= field->getInfo()+".";
+ if(!field->getDescription().empty()){
+ str+= "\n"+field->getDescription()+".";
+ }
+ mainWindow->setInfoText(str);
+}
+
+
+BEGIN_EVENT_TABLE(FieldText, wxStaticText)
+ EVT_HELP(-1, FieldText::onHelp)
+END_EVENT_TABLE()
+
+// ===============================================
+// class App
+// ===============================================
+
+bool App::OnInit(){
+ try{
+ mainWindow= new MainWindow();
+ mainWindow->Show();
+ }
+ catch(const exception &e){
+ wxMessageDialog(NULL, Configuration::ToUnicode(e.what()), Configuration::ToUnicode("Exception"), wxOK | wxICON_ERROR).ShowModal();
+ return 0;
+ }
+ return true;
+}
+
+int App::MainLoop(){
+ try{
+ return wxApp::MainLoop();
+ }
+ catch(const exception &e){
+ wxMessageDialog(NULL, Configuration::ToUnicode(e.what()), Configuration::ToUnicode("Exception"), wxOK | wxICON_ERROR).ShowModal();
+ return 0;
+ }
+}
+
+int App::OnExit(){
+ return 0;
+}
+
+}//end namespace
+
+IMPLEMENT_APP(Configurator::App)
diff --git a/source/configurator/main.h b/source/configurator/main.h
new file mode 100644
index 000000000..1568263ce
--- /dev/null
+++ b/source/configurator/main.h
@@ -0,0 +1,104 @@
+#ifndef _CONFIGURATOR_MAIN_H_
+#define _CONFIGURATOR_MAIN_H_
+
+#include