#include "Window.h"
#include "Widget.h"
#include "CommonWidgets.h"
#include "UiBuilder.h"
#include "Test.h"
BEGIN_NAMESPACE
enum PropertyType // same as VariantType ?
{
PT_Int,
PT_String,
PT_bool,
};
struct TypedProperty
{
VariantType m_type;
AbstractProperty<int>* m_property;
};
// TODO: all this code below is bloaty
// need to trim down or put on a diet the UiBuilder code
// perhaps it is STL making it bloated?
// The object file is almost 1MB
class UiBuilderData
{
public:
void consumeToken(XmlTokenType a_type, const XmlStringSlice& a_text);
void addWidgetType(const char* a_name, WidgetType a_value) {
m_widgetTypeMap.insert(std::make_pair(std::string(a_name), a_value));
}
Vector<TypedWidget> m_parentNode;
WidgetType m_currentType;
WidgetType m_parentType;
std::map<std::string,std::string> m_currentAttributes;
std::string m_currentAttributeName;
std::map<std::string,TypedWidget> m_widgetMap;
std::map<std::string,WidgetType> m_widgetTypeMap;
std::map<std::string,TypedProperty> m_propertySet;
};
Property<String> dummyTextProperty;
Property<bool> dummyBoolProperty;
Property<int> dummyIntProperty;
#define ADD_WIDGET_TYPE(wt) \
m_data->addWidgetType(#wt, WT_##wt)
UiBuilder::UiBuilder(Widget* a_parent)
{
m_data = new UiBuilderData;
TypedWidget parent = { WT_Unknown, a_parent };
m_data->m_parentNode.push_back(parent);
m_data->m_parentType = WT_Unknown;
m_data->m_currentType = WT_Unknown;
dummyTextProperty = "uninitialized!";
ADD_WIDGET_TYPE(VBox);
ADD_WIDGET_TYPE(HBox);
ADD_WIDGET_TYPE(Label);
ADD_WIDGET_TYPE(RadioButton);
ADD_WIDGET_TYPE(CheckBox);
ADD_WIDGET_TYPE(Button);
ADD_WIDGET_TYPE(Slider);
ADD_WIDGET_TYPE(ComboBox);
ADD_WIDGET_TYPE(GroupBox);
ADD_WIDGET_TYPE(LineEdit);
ADD_WIDGET_TYPE(VSpace);
ADD_WIDGET_TYPE(HSpace);
ADD_WIDGET_TYPE(ProgressBar);
ADD_WIDGET_TYPE(Item);
}
UiBuilder::~UiBuilder()
{
delete m_data;
}
void UiBuilder::addGenericProperty(const char* a_name, VariantType a_type, AbstractProperty<int>* a_property)
{
TypedProperty newProperty = { a_type, a_property };
m_data->m_propertySet.insert(std::make_pair(std::string(a_name),newProperty));
}
TypedWidget UiBuilder::findWidget(const char* a_name)
{
return m_data->m_widgetMap[a_name];
}
void UiBuilder::consumeToken(XmlTokenType a_type, const XmlStringSlice& a_text)
{
m_data->consumeToken(a_type, a_text);
}
void UiBuilderData::consumeToken(XmlTokenType a_type, const XmlStringSlice& a_text)
{
if (a_text.m_length <= 0)
{
printf("bad token\n");
return;
}
std::string str(a_text.m_data, a_text.m_length);
switch (a_type)
{
case XT_Text:
// ignore
break;
case XT_TagOpen:
m_currentType = WT_Unknown;
if (m_widgetTypeMap.find(str) != m_widgetTypeMap.end())
m_currentType = m_widgetTypeMap[str];
m_currentAttributes.clear();
break;
case XT_TagStart:
if (m_currentType != WT_Unknown)
{
TypedWidget parentData = m_parentNode.back();
Widget* parent = parentData.m_widget;
Widget* w = 0;
TypedProperty prop = { VT_Unknown, 0 };
if (m_currentAttributes.find("property") != m_currentAttributes.end())
if (m_propertySet.find(m_currentAttributes["property"]) != m_propertySet.end())
prop = m_propertySet[m_currentAttributes["property"]];
switch (m_currentType)
{
case WT_VBox:
w = new VBox(parent); break;
case WT_HBox:
w = new HBox(parent); break;
case WT_Label:
if (prop.m_type == VT_String && prop.m_property)
w = new Label(parent, *(AbstractProperty<String>*)prop.m_property);
else
printf("Label with missing property\n");
break;
case WT_RadioButton:
if (prop.m_type == VT_boolean_t && prop.m_property)
w = new RadioButton(parent, *(AbstractProperty<bool>*)prop.m_property);//, m_currentAttributes["text"].c_str());
else
printf("RadioButton with missing property\n");
break;
case WT_CheckBox:
if (prop.m_type == VT_boolean_t && prop.m_property)
w = new CheckBox(parent, *(AbstractProperty<bool>*)prop.m_property);//, m_currentAttributes["text"].c_str());
else
printf("CheckBox with missing property\n");
break;
case WT_Button:
// TODO: checkable buttons
w = new Button(parent);//, m_currentAttributes["text"].c_str());
break;
case WT_Slider:
if (prop.m_type == VT_int32_t && prop.m_property)
w = new Slider(parent, *(AbstractProperty<int>*)prop.m_property);
else
printf("Slider with missing property\n");
break;
case WT_ComboBox:
if (prop.m_type == VT_int32_t && prop.m_property)
w = new ComboBox(parent, *(AbstractProperty<int>*)prop.m_property);
else
printf("ComboBox with missing property\n");
break;
case WT_GroupBox:
if (prop.m_type == VT_String && prop.m_property)
w = new GroupBox(parent, *(AbstractProperty<String>*)prop.m_property);
else
printf("GroupBox with missing property\n");
break;
case WT_LineEdit:
if (prop.m_type == VT_String && prop.m_property)
w = new LineEdit(parent, *(AbstractProperty<String>*)prop.m_property);
else
printf("LineEdit with missing property\n");
break;
case WT_VSpace:
w = new VSpace(parent); break;
case WT_HSpace:
w = new HSpace(parent); break;
case WT_ProgressBar:
if (prop.m_type == VT_int32_t && prop.m_property)
w = new ProgressBar(parent, *(AbstractProperty<int>*)prop.m_property);
else
printf("ProgressBar with missing property\n");
break;
case WT_Item:
if (parentData.m_type == WT_ComboBox && parent)
((ComboBox*)parent)->addItem(m_currentAttributes["text"].c_str());
else
printf("item not found as child of combobox node\n");
break;
default:
if (prop.m_type == VT_String && prop.m_property)
w = new Label(parent, *(AbstractProperty<String>*)prop.m_property); break;
}
if (w)
{
if (m_currentAttributes.find("text") != m_currentAttributes.end())
{
String val = m_currentAttributes["text"];
switch (m_currentType)
{
case WT_Label: ((Label*)w)->text = val; break;
case WT_RadioButton:((RadioButton*)w)->text = val; break;
case WT_CheckBox: ((CheckBox*)w)->text = val; break;
case WT_Button: ((Button*)w)->text = val; break;
case WT_GroupBox: ((GroupBox*)w)->title = val; break;
case WT_LineEdit: ((LineEdit*)w)->text = val; break;
case WT_Item: break;
default:
printf("invalid attribute for current widget type\n");
}
}
if (m_currentAttributes.find("focus") != m_currentAttributes.end())
{
bool val = (m_currentAttributes["focus"] == "false") ? false : true;
switch (m_currentType)
{
case WT_RadioButton: ((RadioButton*)w)->hasFocus = val; break;
case WT_CheckBox: ((CheckBox*)w)->hasFocus = val; break;
case WT_Button: ((Button*)w)->hasFocus = val; break;
case WT_Slider: ((Slider*)w)->hasFocus = val; break;
case WT_ComboBox: ((ComboBox*)w)->hasFocus = val; break;
case WT_LineEdit: ((LineEdit*)w)->hasFocus = val; break;
default:
printf("invalid attribute for current widget type\n");
}
}
if (m_currentAttributes.find("disabled") != m_currentAttributes.end())
{
bool val = (m_currentAttributes["disabled"] == "false") ? false : true;
switch (m_currentType)
{
case WT_Label: ((Label*)w)->disabled = val; break;
case WT_RadioButton: ((RadioButton*)w)->disabled = val; break;
case WT_CheckBox: ((CheckBox*)w)->disabled = val; break;
case WT_Button: ((Button*)w)->disabled = val; break;
case WT_Slider: ((Slider*)w)->disabled = val; break;
case WT_ComboBox: ((ComboBox*)w)->disabled = val; break;
case WT_GroupBox: ((GroupBox*)w)->disabled = val; break;
case WT_LineEdit: ((LineEdit*)w)->disabled = val; break;
case WT_ProgressBar: ((ProgressBar*)w)->disabled = val; break;
default:
printf("invalid attribute for current widget type\n");
}
}
if (m_currentAttributes.find("default") != m_currentAttributes.end())
{
bool val = (m_currentAttributes["default"] == "false") ? false : true;
switch (m_currentType)
{
case WT_RadioButton: ((RadioButton*)w)->isDefault = val; break;
case WT_CheckBox: ((CheckBox*)w)->isDefault = val; break;
case WT_Button: ((Button*)w)->isDefault = val; break;
//case WT_Slider: ((Slider*)w)->isDefault = val; break;
case WT_ComboBox: ((ComboBox*)w)->isDefault = val; break;
//case WT_LineEdit: ((LineEdit*)w)->isDefault = val; break;
default:
printf("invalid attribute for current widget type\n");
}
}
}
// TODO: check there is a name, and if there is, check it is unique
TypedWidget wid = { m_currentType, w };
m_widgetMap[m_currentAttributes["name"]] = wid;
m_parentNode.push_back(wid);
}
break;
case XT_TagEnd:
if (m_currentType != WT_Unknown && m_parentNode.size())
m_parentNode.pop_back();
break;
case XT_AttributeName:
m_currentAttributeName = str;
break;
case XT_AttributeValue:
if ( str.c_str()[0] == '"' && str.c_str()[str.size()-1] == '"' )
str = str.substr(1, str.size()-2);
m_currentAttributes[m_currentAttributeName] = str;
break;
default:
printf("Got token type=%i data=---%s---\n", a_type, str.c_str());
break;
}
}
END_NAMESPACE