Refactor dialog parsing so each control knows how to parse itself
This commit is contained in:
@@ -50,8 +50,8 @@ cButton::cButton(cDialog& parent) :
|
||||
textClr(parent.getDefTextClr()),
|
||||
fromList("none") {}
|
||||
|
||||
cButton::cButton(cDialog* parent,eControlType t) :
|
||||
cControl(t,*parent),
|
||||
cButton::cButton(cDialog& parent,eControlType t) :
|
||||
cControl(t,parent),
|
||||
fromList("none"),
|
||||
wrapLabel(false) {/* This constructor is only called for LEDs. */}
|
||||
|
||||
@@ -116,6 +116,162 @@ sf::Color cButton::getColour() throw(xUnsupportedProp) {
|
||||
return textClr;
|
||||
}
|
||||
|
||||
std::string cButton::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
std::string name, id;
|
||||
int width = 0, height = 0;
|
||||
bool foundType = false, foundTop = false, foundLeft = false; // required attributes
|
||||
bool foundKey = false;
|
||||
std::string keyMod, keyMain;
|
||||
int keyModRow, keyModCol, keyMainRow, keyMainCol;
|
||||
rectangle frame;
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
else if(name == "wrap"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_WRAP, true);
|
||||
}else if(name == "type"){
|
||||
std::string val;
|
||||
foundType = true;
|
||||
attr->GetValue(&val);
|
||||
if(val == "small")
|
||||
setBtnType(BTN_SM);
|
||||
else if(val == "regular")
|
||||
setBtnType(BTN_REG);
|
||||
else if(val == "large")
|
||||
setBtnType(BTN_LG);
|
||||
else if(val == "help")
|
||||
setBtnType(BTN_HELP);
|
||||
else if(val == "left")
|
||||
setBtnType(BTN_LEFT);
|
||||
else if(val == "right")
|
||||
setBtnType(BTN_RIGHT);
|
||||
else if(val == "up")
|
||||
setBtnType(BTN_UP);
|
||||
else if(val == "down")
|
||||
setBtnType(BTN_DOWN);
|
||||
else if(val == "tiny")
|
||||
setBtnType(BTN_TINY);
|
||||
else if(val == "done")
|
||||
setBtnType(BTN_DONE);
|
||||
else if(val == "tall")
|
||||
setBtnType(BTN_TALL);
|
||||
else if(val == "trait")
|
||||
setBtnType(BTN_TRAIT);
|
||||
else if(val == "push")
|
||||
setBtnType(BTN_PUSH);
|
||||
}else if(name == "color" || name == "colour"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
sf::Color clr;
|
||||
try{
|
||||
clr = parseColor(val);
|
||||
}catch(int){
|
||||
throw xBadVal("button",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
setColour(clr);
|
||||
}else if(name == "def-key"){
|
||||
attr->GetValue(&keyMain);
|
||||
foundKey = true;
|
||||
keyMainRow = attr->Row();
|
||||
keyMainCol = attr->Column();
|
||||
}else if(name == "key-mod"){
|
||||
attr->GetValue(&keyMod);
|
||||
foundKey = true;
|
||||
keyModRow = attr->Row();
|
||||
keyModCol = attr->Column();
|
||||
// }else if(name == "fromlist"){
|
||||
// attr->GetValue(&fromList);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else throw xBadAttr("button",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(parent->getBg() == cDialog::BG_DARK && getBtnType() == BTN_TINY)
|
||||
setColour(sf::Color::White);
|
||||
if(!foundType) throw xMissingAttr("button","type",who.Row(),who.Column(),fname);
|
||||
if(!foundTop) throw xMissingAttr("button","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("button","left",who.Row(),who.Column(),fname);
|
||||
if(foundKey) {
|
||||
cKey theKey;
|
||||
try{
|
||||
theKey = parseKey(keyMod + " " + keyMain);
|
||||
}catch(int){
|
||||
try {
|
||||
theKey = parseKey(keyMain);
|
||||
}catch(int){
|
||||
throw xBadVal("button","def-key",keyMain,keyMainRow,keyMainCol,fname);
|
||||
}
|
||||
throw xBadVal("button","key-mod",keyMod,keyModRow,keyModCol,fname);
|
||||
}
|
||||
attachKey(theKey);
|
||||
}
|
||||
switch(getBtnType()){
|
||||
case BTN_SM:
|
||||
frame.right = frame.left + 23;
|
||||
frame.bottom = frame.top + 23;
|
||||
break;
|
||||
case BTN_LG:
|
||||
frame.right = frame.left + 102;
|
||||
frame.bottom = frame.top + 23;
|
||||
break;
|
||||
case BTN_HELP:
|
||||
frame.right = frame.left + 16;
|
||||
frame.bottom = frame.top + 13;
|
||||
break;
|
||||
case BTN_TINY:
|
||||
case BTN_LED: // this should never happen
|
||||
frame.right = frame.left + 14;
|
||||
frame.bottom = frame.top + 10;
|
||||
break;
|
||||
case BTN_TALL:
|
||||
case BTN_TRAIT:
|
||||
frame.right = frame.left + 63;
|
||||
frame.bottom = frame.top + 40;
|
||||
break;
|
||||
case BTN_PUSH:
|
||||
frame.right = frame.left + 30;
|
||||
frame.bottom = frame.top + 30;
|
||||
break;
|
||||
default:
|
||||
frame.right = frame.left + 63;
|
||||
frame.bottom = frame.top + 23;
|
||||
}
|
||||
if(width > 0)
|
||||
frame.right = frame.left + width;
|
||||
if(height > 0)
|
||||
frame.bottom = frame.top + height;
|
||||
setBounds(frame);
|
||||
std::string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
std::string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::ELEMENT && val == "key"){
|
||||
// TODO: There's surely a better way to do this
|
||||
if(content.length() > 0) throw xBadVal("button",xBadVal::CONTENT,content + val,node->Row(),node->Column(),fname);
|
||||
// labelWithKey = true;
|
||||
}else if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("button",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
setText(content);
|
||||
return id;
|
||||
}
|
||||
|
||||
// Indices within the buttons array.
|
||||
size_t cButton::btnGW[14] = {
|
||||
0, // BTN_SM
|
||||
@@ -190,7 +346,7 @@ void cLed::init(){
|
||||
}
|
||||
}
|
||||
|
||||
cLed::cLed(cDialog* parent) :
|
||||
cLed::cLed(cDialog& parent) :
|
||||
cButton(parent,CTRL_LED),
|
||||
state(led_off),
|
||||
textFont(FONT_BOLD),
|
||||
@@ -282,8 +438,8 @@ void cLed::restore(storage_t to) {
|
||||
else setState(led_off);
|
||||
}
|
||||
|
||||
cLedGroup::cLedGroup(cDialog* parent) :
|
||||
cControl(CTRL_GROUP,*parent),
|
||||
cLedGroup::cLedGroup(cDialog& parent) :
|
||||
cControl(CTRL_GROUP,parent),
|
||||
fromList("none") {}
|
||||
|
||||
cButton::~cButton() {}
|
||||
@@ -332,6 +488,106 @@ eLedState cLed::getState(){
|
||||
return state;
|
||||
}
|
||||
|
||||
std::string cLed::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
std::string name, id;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false; // requireds
|
||||
rectangle frame;
|
||||
if(parent->getBg() == cDialog::BG_DARK)
|
||||
setColour(sf::Color::White);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
else if(name == "state"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "red") setState(led_red);
|
||||
else if(val == "green") setState(led_green);
|
||||
else if(val == "off") setState(led_off);
|
||||
else throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
// }else if(name == "fromlist"){
|
||||
// attr->GetValue(&fromList);
|
||||
}else if(name == "font"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "dungeon")
|
||||
setFormat(TXT_FONT, FONT_DUNGEON);
|
||||
else if(val == "plain")
|
||||
setFormat(TXT_FONT, FONT_PLAIN);
|
||||
else if(val == "bold")
|
||||
setFormat(TXT_FONT, FONT_BOLD);
|
||||
else if(val == "maidenword")
|
||||
setFormat(TXT_FONT, FONT_MAIDWORD);
|
||||
else throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "size"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "large")
|
||||
setFormat(TXT_SIZE, 12);
|
||||
else if(val == "small")
|
||||
setFormat(TXT_SIZE, 10);
|
||||
else if(val == "title")
|
||||
setFormat(TXT_SIZE, 18);
|
||||
else throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "color" || name == "colour"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
sf::Color clr;
|
||||
try{
|
||||
clr = parseColor(val);
|
||||
}catch(int){
|
||||
throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
setColour(clr);
|
||||
} else if(name == "wrap") {
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true")
|
||||
setFormat(TXT_WRAP, true);
|
||||
else setFormat(TXT_WRAP, false);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else throw xBadAttr("led",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("led","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("led","left",who.Row(),who.Column(),fname);
|
||||
if(width > 0) {
|
||||
frame.right = frame.left + width;
|
||||
}else{
|
||||
frame.right = frame.left + 14;
|
||||
}
|
||||
if(height > 0) {
|
||||
frame.bottom = frame.top + height;
|
||||
}else{
|
||||
frame.bottom = frame.top + 10;
|
||||
}
|
||||
setBounds(frame);
|
||||
std::string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
std::string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("led",xBadVal::CONTENT,content + val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
setText(content);
|
||||
return id;
|
||||
}
|
||||
|
||||
void cLedGroup::addChoice(cLed* ctrl, std::string key) {
|
||||
choices[key] = ctrl;
|
||||
if(ctrl->getState() != led_off)
|
||||
@@ -553,3 +809,32 @@ void cLedGroup::restore(storage_t to) {
|
||||
setSelected(boost::any_cast<std::string>(to["led-select"]));
|
||||
else setSelected("");
|
||||
}
|
||||
|
||||
std::string cLedGroup::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Element> node;
|
||||
std::string name, id;
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
// else if(name == "fromlist")
|
||||
// attr->GetValue(&fromList);
|
||||
else throw xBadAttr("group",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
std::string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::ELEMENT && val == "led"){
|
||||
auto led = parent->parse<cLed>(*node);
|
||||
addChoice(led.second, led.first);
|
||||
}else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("group",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
recalcRect();
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ class cButton : public cControl {
|
||||
public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
@@ -83,7 +84,7 @@ protected:
|
||||
/// Construct a new button.
|
||||
/// @param parent The parent dialog.
|
||||
/// @param t The type of control. Should be either CTRL_LED or CTRL_BTN.
|
||||
cButton(cDialog* parent,eControlType t);
|
||||
cButton(cDialog& parent,eControlType t);
|
||||
private:
|
||||
bool labelWithKey;
|
||||
std::string fromList;
|
||||
@@ -111,6 +112,7 @@ public:
|
||||
/// default toggle-selected action of an LED.
|
||||
/// @return true to indicate the event should continue.
|
||||
static bool noAction(cDialog&,std::string,eKeyMod) {return true;}
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw();
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
@@ -121,7 +123,7 @@ public:
|
||||
void restore(storage_t to);
|
||||
/// Create a new LED button.
|
||||
/// @param parent The parent dialog.
|
||||
explicit cLed(cDialog* parent);
|
||||
explicit cLed(cDialog& parent);
|
||||
virtual ~cLed();
|
||||
/// Set the LED's current state,.
|
||||
/// @param to The new state.
|
||||
@@ -169,6 +171,7 @@ class cLedGroup : public cControl {
|
||||
cLedGroup& operator=(cLedGroup& other) = delete;
|
||||
cLedGroup(cLedGroup& other) = delete;
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
/// @copydoc cControl::attachClickHandler()
|
||||
///
|
||||
/// The click handler is called whenever an LED in the group is clicked, even if it's the currently selected LED.
|
||||
@@ -209,7 +212,7 @@ public:
|
||||
sf::Color getColour() throw(xUnsupportedProp);
|
||||
/// Create a new LED group.
|
||||
/// @param parent The parent dialog.
|
||||
explicit cLedGroup(cDialog* parent);
|
||||
explicit cLedGroup(cDialog& parent);
|
||||
bool isClickable();
|
||||
bool handleClick(location where);
|
||||
virtual ~cLedGroup();
|
||||
|
||||
@@ -86,9 +86,14 @@ public:
|
||||
/// to be drawn, handleClick() when a mousedown event is received within the control's bounding rect, and
|
||||
/// triggerClickHandler() if a click occurs, either because handleClick() returns true or because
|
||||
/// a keyboard event is received that should trigger the control.
|
||||
///
|
||||
/// All control subclasses must have a constructor that takes a single cDialog& parameter,
|
||||
/// in order for the parsing template to work.
|
||||
class cControl {
|
||||
public:
|
||||
using storage_t = std::map<std::string, boost::any>;
|
||||
/// Parses the control from an XML element
|
||||
virtual std::string parse(ticpp::Element& who, std::string fname) = 0;
|
||||
/// Attach a keyboard shortcut to a control. Pressing the keyboard shortcut is equivalent to clicking the control.
|
||||
/// @param key The desired keyboard shortcut.
|
||||
void attachKey(cKey key);
|
||||
@@ -226,6 +231,16 @@ public:
|
||||
cControl& operator=(cControl& other) = delete;
|
||||
cControl(cControl& other) = delete;
|
||||
protected:
|
||||
/// Parses an HTML colour code.
|
||||
/// Recognizes three-digit hex, six-digit hex, and HTML colour names.
|
||||
/// @param code The colour code to parse.
|
||||
static sf::Color parseColor(std::string code);
|
||||
/// Parses a key code.
|
||||
/// @param what The code to parse.
|
||||
static cKey parseKey(std::string what);
|
||||
/// Filters newlines and tabs from a string, leaving spaces intact.
|
||||
/// @param toFilter The string to filter.
|
||||
static std::string dlogStringFilter(std::string toFilter);
|
||||
/// The parent dialog of the control.
|
||||
/// May be null, if the control was created via cControl(eControlType,sf::RenderWindow&).
|
||||
cDialog* parent;
|
||||
@@ -253,6 +268,7 @@ protected:
|
||||
/// Intended to be called from handleClick(), where there is usually a minor event loop happening.
|
||||
void redraw();
|
||||
private:
|
||||
friend class cDialog; // TODO: This is only so it can access parseColour... hack!
|
||||
eControlType type;
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ const short cDialog::BG_DARK = 5, cDialog::BG_LIGHT = 16;
|
||||
short cDialog::defaultBackground = cDialog::BG_DARK;
|
||||
cDialog* cDialog::topWindow = nullptr;
|
||||
|
||||
static std::string generateRandomString(){
|
||||
std::string cDialog::generateRandomString(){
|
||||
// Not bothering to seed, because it doesn't actually matter if it's truly random.
|
||||
// Though, this will be called after srand() is called in main() anyway.
|
||||
int n_chars = rand() % 100;
|
||||
@@ -45,144 +45,7 @@ static std::string generateRandomString(){
|
||||
return s;
|
||||
}
|
||||
|
||||
template<> pair<string,cPict*> cDialog::parse(Element& who /*pict*/){
|
||||
std::pair<std::string,cPict*> p;
|
||||
Iterator<Attribute> attr;
|
||||
std::string name;
|
||||
ePicType type;
|
||||
bool wide = false, tall = false, custom = false, tiny = false;
|
||||
bool foundTop = false, foundLeft = false, foundType = false, foundNum = false; // required attributes
|
||||
rectangle frame;
|
||||
int width = 0, height = 0;
|
||||
p.second = new cPict(*this);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&p.first);
|
||||
else if(name == "type"){
|
||||
std::string val;
|
||||
foundType = true;
|
||||
attr->GetValue(&val);
|
||||
if(val == "blank"){
|
||||
p.second->setPict(cPict::BLANK, PIC_TER);
|
||||
foundNum = true;
|
||||
continue;
|
||||
}else if(val == "ter")
|
||||
type = PIC_TER;
|
||||
else if(val == "teranim")
|
||||
type = PIC_TER_ANIM;
|
||||
else if(val == "monst")
|
||||
type = PIC_MONST;
|
||||
else if(val == "dlog")
|
||||
type = PIC_DLOG;
|
||||
else if(val == "talk")
|
||||
type = PIC_TALK;
|
||||
else if(val == "scen")
|
||||
type = PIC_SCEN;
|
||||
else if(val == "item")
|
||||
type = PIC_ITEM;
|
||||
else if(val == "pc")
|
||||
type = PIC_PC;
|
||||
else if(val == "field")
|
||||
type = PIC_FIELD;
|
||||
else if(val == "boom")
|
||||
type = PIC_BOOM;
|
||||
else if(val == "missile")
|
||||
type = PIC_MISSILE;
|
||||
else if(val == "full")
|
||||
type = PIC_FULL;
|
||||
else if(val == "map")
|
||||
type = PIC_TER_MAP;
|
||||
else if(val == "status")
|
||||
type = PIC_STATUS;
|
||||
else throw xBadVal("pict",name,val,attr->Row(),attr->Column(),fname);
|
||||
if(foundNum) {
|
||||
pic_num_t wasPic = p.second->getPicNum();
|
||||
p.second->setPict(wasPic, type);
|
||||
}
|
||||
}else if(name == "custom"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") custom = true;
|
||||
}else if(name == "scaled"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") p.second->setFormat(TXT_WRAP, false);
|
||||
}else if(name == "size"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "wide") wide = true;
|
||||
else if(val == "tall") tall = true;
|
||||
else if(val == "large") wide = tall = true;
|
||||
else if(val == "small") tiny = true;
|
||||
else throw xBadVal("pict",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "def-key"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
// TODO: The modifiers are now in key-mod, so this needs to be updated
|
||||
try{
|
||||
p.second->attachKey(parseKey(val));
|
||||
}catch(int){
|
||||
throw xBadVal("pict",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
}else if(name == "num"){
|
||||
pic_num_t newPic;
|
||||
attr->GetValue(&newPic), foundNum = true;
|
||||
if(foundType) p.second->setPict(newPic, type);
|
||||
else p.second->setPict(newPic);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else if(name == "framed"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") p.second->setFormat(TXT_FRAME, true);
|
||||
else p.second->setFormat(TXT_FRAME, false);
|
||||
}else throw xBadAttr("pict",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundType) throw xMissingAttr("pict","type",who.Row(),who.Column(),fname);
|
||||
if(!foundNum) throw xMissingAttr("pict","num",who.Row(),who.Column(),fname);
|
||||
if(!foundTop) throw xMissingAttr("pict","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("pict","left",who.Row(),who.Column(),fname);
|
||||
if(wide || tall) {
|
||||
pic_num_t wasPic = p.second->getPicNum();
|
||||
if(wide && !tall && p.second->getPicType() == PIC_MONST) p.second->setPict(wasPic, PIC_MONST_WIDE);
|
||||
else if(!wide && tall && p.second->getPicType() == PIC_MONST) p.second->setPict(wasPic, PIC_MONST_TALL);
|
||||
else if(wide && tall){
|
||||
if(p.second->getPicType() == PIC_MONST) p.second->setPict(wasPic, PIC_MONST_LG);
|
||||
else if(p.second->getPicType() == PIC_SCEN) p.second->setPict(wasPic, PIC_SCEN_LG);
|
||||
else if(p.second->getPicType() == PIC_DLOG) p.second->setPict(wasPic, PIC_DLOG_LG);
|
||||
}
|
||||
} else if(tiny && type == PIC_ITEM) {
|
||||
pic_num_t wasPic = p.second->getPicNum();
|
||||
p.second->setPict(wasPic, PIC_TINY_ITEM);
|
||||
}
|
||||
frame.right = frame.left;
|
||||
frame.bottom = frame.top;
|
||||
if(width > 0 || height > 0 || p.second->getPicType() == PIC_FULL){
|
||||
frame.right = frame.left + width;
|
||||
frame.bottom = frame.top + height;
|
||||
}
|
||||
p.second->setBounds(frame);
|
||||
pic_num_t wasPic = p.second->getPicNum();
|
||||
if(custom) {
|
||||
p.second->setPict(wasPic, p.second->getPicType() + PIC_CUSTOM);
|
||||
} else p.second->setPict(wasPic, p.second->getPicType());
|
||||
// The above line also sets the graphic's bounding rect, if necessary
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static string dlogStringFilter(string toFilter) {
|
||||
string cControl::dlogStringFilter(string toFilter) {
|
||||
string filtered;
|
||||
bool found_nl = false;
|
||||
for(char c : toFilter) {
|
||||
@@ -196,108 +59,7 @@ static string dlogStringFilter(string toFilter) {
|
||||
return filtered;
|
||||
}
|
||||
|
||||
template<> pair<string,cTextMsg*> cDialog::parse(Element& who /*text*/){
|
||||
pair<string,cTextMsg*> p;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
string name;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false; // top and left are required attributes
|
||||
rectangle frame;
|
||||
p.second = new cTextMsg(*this);
|
||||
if(bg == BG_DARK) p.second->setColour(sf::Color::White);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&p.first);
|
||||
else if(name == "framed"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") p.second->setFormat(TXT_FRAME, true);
|
||||
}else if(name == "font"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "dungeon")
|
||||
p.second->setFormat(TXT_FONT, FONT_DUNGEON);
|
||||
else if(val == "plain")
|
||||
p.second->setFormat(TXT_FONT, FONT_PLAIN);
|
||||
else if(val == "bold")
|
||||
p.second->setFormat(TXT_FONT, FONT_BOLD);
|
||||
else if(val == "maidenword")
|
||||
p.second->setFormat(TXT_FONT, FONT_MAIDWORD);
|
||||
else throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "size"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "large")
|
||||
p.second->setFormat(TXT_SIZE, 12);
|
||||
else if(val == "small")
|
||||
p.second->setFormat(TXT_SIZE, 10);
|
||||
else if(val == "title")
|
||||
p.second->setFormat(TXT_SIZE, 18);
|
||||
else throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "color" || name == "colour"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
sf::Color clr;
|
||||
try{
|
||||
clr = parseColor(val);
|
||||
}catch(int){
|
||||
throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
p.second->setColour(clr);
|
||||
}else if(name == "def-key"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
try{
|
||||
p.second->attachKey(parseKey(val));
|
||||
}catch(int){
|
||||
throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
// }else if(name == "fromlist"){
|
||||
// attr->GetValue(&p.second->fromList);
|
||||
}else throw xBadAttr("text",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("text","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("text","left",who.Row(),who.Column(),fname);
|
||||
frame.right = frame.left + width;
|
||||
frame.bottom = frame.top + height;
|
||||
p.second->setBounds(frame);
|
||||
string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
// TODO: De-magic the | character
|
||||
if(type == TiXmlNode::ELEMENT && val == "br") content += '|'; // because vertical bar is replaced by a newline when drawing strings
|
||||
else if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("text",xBadVal::CONTENT,content + val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
p.second->setText(content);
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an HTML-style colour string, recognizing three-digit hex, six-digit hex, and HTML colour names.
|
||||
*/
|
||||
sf::Color cDialog::parseColor(string what){
|
||||
sf::Color cControl::parseColor(string what){
|
||||
sf::Color clr;
|
||||
if(what[0] == '#'){
|
||||
unsigned int r,g,b;
|
||||
@@ -347,168 +109,7 @@ sf::Color cDialog::parseColor(string what){
|
||||
return clr;
|
||||
}
|
||||
|
||||
template<> pair<string,cButton*> cDialog::parse(Element& who /*button*/){
|
||||
pair<string,cButton*> p;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
string name;
|
||||
int width = 0, height = 0;
|
||||
bool foundType = false, foundTop = false, foundLeft = false; // required attributes
|
||||
bool foundKey = false;
|
||||
std::string keyMod, keyMain;
|
||||
int keyModRow, keyModCol, keyMainRow, keyMainCol;
|
||||
rectangle frame;
|
||||
p.second = new cButton(*this);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&p.first);
|
||||
else if(name == "wrap"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") p.second->setFormat(TXT_WRAP, true);
|
||||
}else if(name == "type"){
|
||||
std::string val;
|
||||
foundType = true;
|
||||
attr->GetValue(&val);
|
||||
if(val == "small")
|
||||
p.second->setBtnType(BTN_SM);
|
||||
else if(val == "regular")
|
||||
p.second->setBtnType(BTN_REG);
|
||||
else if(val == "large")
|
||||
p.second->setBtnType(BTN_LG);
|
||||
else if(val == "help")
|
||||
p.second->setBtnType(BTN_HELP);
|
||||
else if(val == "left")
|
||||
p.second->setBtnType(BTN_LEFT);
|
||||
else if(val == "right")
|
||||
p.second->setBtnType(BTN_RIGHT);
|
||||
else if(val == "up")
|
||||
p.second->setBtnType(BTN_UP);
|
||||
else if(val == "down")
|
||||
p.second->setBtnType(BTN_DOWN);
|
||||
else if(val == "tiny")
|
||||
p.second->setBtnType(BTN_TINY);
|
||||
else if(val == "done")
|
||||
p.second->setBtnType(BTN_DONE);
|
||||
else if(val == "tall")
|
||||
p.second->setBtnType(BTN_TALL);
|
||||
else if(val == "trait")
|
||||
p.second->setBtnType(BTN_TRAIT);
|
||||
else if(val == "push")
|
||||
p.second->setBtnType(BTN_PUSH);
|
||||
}else if(name == "color" || name == "colour"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
sf::Color clr;
|
||||
try{
|
||||
clr = parseColor(val);
|
||||
}catch(int){
|
||||
throw xBadVal("button",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
p.second->setColour(clr);
|
||||
}else if(name == "def-key"){
|
||||
attr->GetValue(&keyMain);
|
||||
foundKey = true;
|
||||
keyMainRow = attr->Row();
|
||||
keyMainCol = attr->Column();
|
||||
}else if(name == "key-mod"){
|
||||
attr->GetValue(&keyMod);
|
||||
foundKey = true;
|
||||
keyModRow = attr->Row();
|
||||
keyModCol = attr->Column();
|
||||
// }else if(name == "fromlist"){
|
||||
// attr->GetValue(&p.second->fromList);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else throw xBadAttr("button",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(bg == BG_DARK && p.second->getBtnType() == BTN_TINY) p.second->setColour(sf::Color::White);
|
||||
if(!foundType) throw xMissingAttr("button","type",who.Row(),who.Column(),fname);
|
||||
if(!foundTop) throw xMissingAttr("button","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("button","left",who.Row(),who.Column(),fname);
|
||||
if(foundKey) {
|
||||
cKey theKey;
|
||||
try{
|
||||
theKey = parseKey(keyMod + " " + keyMain);
|
||||
}catch(int){
|
||||
try {
|
||||
theKey = parseKey(keyMain);
|
||||
}catch(int){
|
||||
throw xBadVal("button","def-key",keyMain,keyMainRow,keyMainCol,fname);
|
||||
}
|
||||
throw xBadVal("button","key-mod",keyMod,keyModRow,keyModCol,fname);
|
||||
}
|
||||
p.second->attachKey(theKey);
|
||||
}
|
||||
switch(p.second->getBtnType()){
|
||||
case BTN_SM:
|
||||
frame.right = frame.left + 23;
|
||||
frame.bottom = frame.top + 23;
|
||||
break;
|
||||
case BTN_LG:
|
||||
frame.right = frame.left + 102;
|
||||
frame.bottom = frame.top + 23;
|
||||
break;
|
||||
case BTN_HELP:
|
||||
frame.right = frame.left + 16;
|
||||
frame.bottom = frame.top + 13;
|
||||
break;
|
||||
case BTN_TINY:
|
||||
case BTN_LED: // this should never happen
|
||||
frame.right = frame.left + 14;
|
||||
frame.bottom = frame.top + 10;
|
||||
break;
|
||||
case BTN_TALL:
|
||||
case BTN_TRAIT:
|
||||
frame.right = frame.left + 63;
|
||||
frame.bottom = frame.top + 40;
|
||||
break;
|
||||
case BTN_PUSH:
|
||||
frame.right = frame.left + 30;
|
||||
frame.bottom = frame.top + 30;
|
||||
break;
|
||||
default:
|
||||
frame.right = frame.left + 63;
|
||||
frame.bottom = frame.top + 23;
|
||||
}
|
||||
if(width > 0)
|
||||
frame.right = frame.left + width;
|
||||
if(height > 0)
|
||||
frame.bottom = frame.top + height;
|
||||
p.second->setBounds(frame);
|
||||
string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::ELEMENT && val == "key"){
|
||||
// TODO: There's surely a better way to do this
|
||||
if(content.length() > 0) throw xBadVal("button",xBadVal::CONTENT,content + val,node->Row(),node->Column(),fname);
|
||||
// p.second->labelWithKey = true;
|
||||
}else if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("button",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
p.second->setText(content);
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
cKey cDialog::parseKey(string what){
|
||||
cKey cControl::parseKey(string what){
|
||||
cKey key;
|
||||
key.spec = false;
|
||||
key.c = 0;
|
||||
@@ -564,271 +165,6 @@ cKey cDialog::parseKey(string what){
|
||||
return key;
|
||||
}
|
||||
|
||||
template<> pair<string,cLed*> cDialog::parse(Element& who /*LED*/){
|
||||
pair<string,cLed*> p;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
string name;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false; // requireds
|
||||
rectangle frame;
|
||||
p.second = new cLed(this);
|
||||
if(bg == BG_DARK) p.second->setColour(sf::Color::White);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&p.first);
|
||||
else if(name == "state"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "red") p.second->setState(led_red);
|
||||
else if(val == "green") p.second->setState(led_green);
|
||||
else if(val == "off") p.second->setState(led_off);
|
||||
else throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
// }else if(name == "fromlist"){
|
||||
// attr->GetValue(&p.second->fromList);
|
||||
}else if(name == "font"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "dungeon")
|
||||
p.second->setFormat(TXT_FONT, FONT_DUNGEON);
|
||||
else if(val == "plain")
|
||||
p.second->setFormat(TXT_FONT, FONT_PLAIN);
|
||||
else if(val == "bold")
|
||||
p.second->setFormat(TXT_FONT, FONT_BOLD);
|
||||
else if(val == "maidenword")
|
||||
p.second->setFormat(TXT_FONT, FONT_MAIDWORD);
|
||||
else throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "size"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "large")
|
||||
p.second->setFormat(TXT_SIZE, 12);
|
||||
else if(val == "small")
|
||||
p.second->setFormat(TXT_SIZE, 10);
|
||||
else if(val == "title")
|
||||
p.second->setFormat(TXT_SIZE, 18);
|
||||
else throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "color" || name == "colour"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
sf::Color clr;
|
||||
try{
|
||||
clr = parseColor(val);
|
||||
}catch(int){
|
||||
throw xBadVal("led",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
p.second->setColour(clr);
|
||||
} else if(name == "wrap") {
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true")
|
||||
p.second->setFormat(TXT_WRAP, true);
|
||||
else p.second->setFormat(TXT_WRAP, false);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else throw xBadAttr("led",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("led","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("led","left",who.Row(),who.Column(),fname);
|
||||
if(width > 0) {
|
||||
frame.right = frame.left + width;
|
||||
}else{
|
||||
frame.right = frame.left + 14;
|
||||
}
|
||||
if(height > 0) {
|
||||
frame.bottom = frame.top + height;
|
||||
}else{
|
||||
frame.bottom = frame.top + 10;
|
||||
}
|
||||
p.second->setBounds(frame);
|
||||
string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("led",xBadVal::CONTENT,content + val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
p.second->setText(content);
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
template<> pair<string,cLedGroup*> cDialog::parse(Element& who /*group*/){
|
||||
pair<string,cLedGroup*> p;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Element> node;
|
||||
string name;
|
||||
p.second = new cLedGroup(this);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&p.first);
|
||||
// else if(name == "fromlist")
|
||||
// attr->GetValue(&p.second->fromList);
|
||||
else throw xBadAttr("group",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::ELEMENT && val == "led"){
|
||||
auto led = parse<cLed>(*node);
|
||||
p.second->addChoice(led.second, led.first);
|
||||
}else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("group",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
p.second->recalcRect();
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
template<> pair<string,cTextField*> cDialog::parse(Element& who /*field*/){
|
||||
pair<string,cTextField*> p;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
string name;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false; // requireds
|
||||
rectangle frame;
|
||||
p.second = new cTextField(this);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&p.first);
|
||||
else if(name == "type"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "int")
|
||||
p.second->setInputType(FLD_INT);
|
||||
else if(val == "uint")
|
||||
p.second->setInputType(FLD_UINT);
|
||||
else if(val == "real")
|
||||
p.second->setInputType(FLD_REAL);
|
||||
else if(val == "text")
|
||||
p.second->setInputType(FLD_TEXT);
|
||||
else throw xBadVal("field",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else if(name == "tab-order"){
|
||||
attr->GetValue(&p.second->tabOrder);
|
||||
}else throw xBadAttr("field",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("field","top",attr->Row(),attr->Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("field","left",attr->Row(),attr->Column(),fname);
|
||||
frame.right = frame.left + width;
|
||||
frame.bottom = frame.top + height;
|
||||
p.second->setBounds(frame);
|
||||
string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("field",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
p.second->setText(content);
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
// Note: This specialization must come last because it requires the other specializations
|
||||
template<> pair<string,cStack*> cDialog::parse(Element& who /*stack*/) {
|
||||
pair<string, cStack*> p;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Element> node;
|
||||
string name;
|
||||
p.second = new cStack(*this);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++) {
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&p.first);
|
||||
else if(name == "pages") {
|
||||
size_t val;
|
||||
attr->GetValue(&val);
|
||||
p.second->setPageCount(val);
|
||||
} else throw xBadAttr("stack",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
vector<string> stack;
|
||||
for(node = node.begin(&who); node != node.end(); node++) {
|
||||
string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::ELEMENT) {
|
||||
if(val == "field") {
|
||||
auto field = parse<cTextField>(*node);
|
||||
controls.insert(field);
|
||||
stack.push_back(field.first);
|
||||
tabOrder.push_back(field);
|
||||
} else if(val == "text") {
|
||||
auto text = parse<cTextMsg>(*node);
|
||||
controls.insert(text);
|
||||
stack.push_back(text.first);
|
||||
} else if(val == "pict") {
|
||||
auto pict = parse<cPict>(*node);
|
||||
controls.insert(pict);
|
||||
stack.push_back(pict.first);
|
||||
} else if(val == "button") {
|
||||
auto button = parse<cButton>(*node);
|
||||
controls.insert(button);
|
||||
stack.push_back(button.first);
|
||||
} else if(val == "led") {
|
||||
auto led = parse<cLed>(*node);
|
||||
controls.insert(led);
|
||||
stack.push_back(led.first);
|
||||
} else if(val == "group") {
|
||||
auto group = parse<cLedGroup>(*node);
|
||||
controls.insert(group);
|
||||
stack.push_back(group.first);
|
||||
} else throw xBadNode(val,node->Row(),node->Column(),fname);
|
||||
} else if(type != TiXmlNode::COMMENT)
|
||||
throw xBadVal("stack",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
p.second->controls = stack;
|
||||
p.second->recalcRect();
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
cDialog::cDialog(cDialog* p) : parent(p) {}
|
||||
|
||||
cDialog::cDialog(std::string path, cDialog* p) : parent(p) {
|
||||
@@ -865,7 +201,7 @@ void cDialog::loadFromFile(std::string path){
|
||||
}else if(name == "fore"){
|
||||
sf::Color clr;
|
||||
try{
|
||||
clr = parseColor(val);
|
||||
clr = cControl::parseColor(val);
|
||||
}catch(int){
|
||||
throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
|
||||
@@ -39,12 +39,10 @@ class cDialog {
|
||||
std::map<std::string,cControl*> controls;
|
||||
short bg;
|
||||
sf::Color defTextClr;
|
||||
template<class T> std::pair<std::string,T*> parse(ticpp::Element& who);
|
||||
sf::Color parseColor(std::string what);
|
||||
cKey parseKey(std::string what);
|
||||
sf::RenderWindow win;
|
||||
std::string currentFocus;
|
||||
cDialog* parent;
|
||||
std::string generateRandomString();
|
||||
void loadFromFile(std::string path);
|
||||
template<typename Iter> void handleTabOrder(std::string& itemHit, Iter begin, Iter end);
|
||||
std::vector<std::pair<std::string,cTextField*>> tabOrder;
|
||||
@@ -188,6 +186,22 @@ public:
|
||||
static bool sendInput(cKey key);
|
||||
/// Sets whether to animate graphics in dialogs.
|
||||
static bool doAnimations;
|
||||
/// Adds a new control described by the passed XML element.
|
||||
/// @tparam Ctrl The type of control to add.
|
||||
/// @param who The XML element describing the control.
|
||||
/// @note It is up to the caller to ensure that that the element
|
||||
/// passed describes the type of control being requested.
|
||||
template<class Ctrl> std::pair<std::string,Ctrl*> parse(ticpp::Element& who) {
|
||||
std::pair<std::string,Ctrl*> p;
|
||||
p.second = new Ctrl(*this);
|
||||
p.first = p.second->parse(who, fname);
|
||||
if(p.first == ""){
|
||||
do{
|
||||
p.first = generateRandomString();
|
||||
}while(controls.find(p.first) != controls.end());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
cDialog& operator=(cDialog& other) = delete;
|
||||
cDialog(cDialog& other) = delete;
|
||||
private:
|
||||
|
||||
@@ -197,8 +197,8 @@ bool cTextField::hasFocus() {
|
||||
return haveFocus;
|
||||
}
|
||||
|
||||
cTextField::cTextField(cDialog* parent) :
|
||||
cControl(CTRL_FIELD,*parent),
|
||||
cTextField::cTextField(cDialog& parent) :
|
||||
cControl(CTRL_FIELD,parent),
|
||||
color(sf::Color::Black),
|
||||
insertionPoint(-1),
|
||||
selectionPoint(0),
|
||||
@@ -630,6 +630,63 @@ void cTextField::handleInput(cKey key) {
|
||||
selectionPoint = sp;
|
||||
}
|
||||
|
||||
std::string cTextField::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
std::string name, id;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false; // requireds
|
||||
rectangle frame;
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
else if(name == "type"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "int")
|
||||
setInputType(FLD_INT);
|
||||
else if(val == "uint")
|
||||
setInputType(FLD_UINT);
|
||||
else if(val == "real")
|
||||
setInputType(FLD_REAL);
|
||||
else if(val == "text")
|
||||
setInputType(FLD_TEXT);
|
||||
else throw xBadVal("field",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else if(name == "tab-order"){
|
||||
attr->GetValue(&tabOrder);
|
||||
}else throw xBadAttr("field",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("field","top",attr->Row(),attr->Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("field","left",attr->Row(),attr->Column(),fname);
|
||||
frame.right = frame.left + width;
|
||||
frame.bottom = frame.top + height;
|
||||
setBounds(frame);
|
||||
std::string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
std::string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("field",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
setText(content);
|
||||
return id;
|
||||
}
|
||||
|
||||
aTextInsert::aTextInsert(cTextField& in, int at, std::string text) : cAction("insert text"), in(in), at(at), text(text) {}
|
||||
|
||||
void aTextInsert::undo() {
|
||||
|
||||
@@ -33,6 +33,7 @@ enum eFldType {
|
||||
/// There is no Unicode support.
|
||||
class cTextField : public cControl {
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
|
||||
/// @copydoc cControl::attachFocusHandler()
|
||||
/// For text fields, this is triggered when it loses or gains the input focus.
|
||||
@@ -54,7 +55,7 @@ public:
|
||||
sf::Color getColour() throw(xUnsupportedProp);
|
||||
/// Create a new editable text field.
|
||||
/// @param parent The parent dialog.
|
||||
explicit cTextField(cDialog* parent);
|
||||
explicit cTextField(cDialog& parent);
|
||||
bool isClickable();
|
||||
virtual ~cTextField();
|
||||
void draw();
|
||||
|
||||
@@ -73,6 +73,99 @@ short cTextMsg::getFormat(eFormat prop) throw(xUnsupportedProp){
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string cTextMsg::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
std::string name, id;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false; // top and left are required attributes
|
||||
rectangle frame;
|
||||
if(parent->getBg() == cDialog::BG_DARK)
|
||||
setColour(sf::Color::White);
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
else if(name == "framed"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_FRAME, true);
|
||||
}else if(name == "font"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "dungeon")
|
||||
setFormat(TXT_FONT, FONT_DUNGEON);
|
||||
else if(val == "plain")
|
||||
setFormat(TXT_FONT, FONT_PLAIN);
|
||||
else if(val == "bold")
|
||||
setFormat(TXT_FONT, FONT_BOLD);
|
||||
else if(val == "maidenword")
|
||||
setFormat(TXT_FONT, FONT_MAIDWORD);
|
||||
else throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "size"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "large")
|
||||
setFormat(TXT_SIZE, 12);
|
||||
else if(val == "small")
|
||||
setFormat(TXT_SIZE, 10);
|
||||
else if(val == "title")
|
||||
setFormat(TXT_SIZE, 18);
|
||||
else throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "color" || name == "colour"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
sf::Color clr;
|
||||
try{
|
||||
clr = parseColor(val);
|
||||
}catch(int){
|
||||
throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
setColour(clr);
|
||||
}else if(name == "def-key"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
try{
|
||||
attachKey(parseKey(val));
|
||||
}catch(int){
|
||||
throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
// }else if(name == "fromlist"){
|
||||
// attr->GetValue(&p.second->fromList);
|
||||
}else throw xBadAttr("text",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("text","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("text","left",who.Row(),who.Column(),fname);
|
||||
frame.right = frame.left + width;
|
||||
frame.bottom = frame.top + height;
|
||||
setBounds(frame);
|
||||
std::string content;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
std::string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
// TODO: De-magic the | character
|
||||
if(type == TiXmlNode::ELEMENT && val == "br") content += '|'; // because vertical bar is replaced by a newline when drawing strings
|
||||
else if(type == TiXmlNode::TEXT)
|
||||
content += dlogStringFilter(val);
|
||||
else if(type != TiXmlNode::COMMENT) {
|
||||
val = '<' + val + '>';
|
||||
throw xBadVal("text",xBadVal::CONTENT,content + val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
}
|
||||
setText(content);
|
||||
return id;
|
||||
}
|
||||
|
||||
cTextMsg::cTextMsg(cDialog& parent) :
|
||||
cControl(CTRL_TEXT,parent),
|
||||
drawFramed(false),
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
/// This class can also create a frame for grouping controls or a clickable area.
|
||||
class cTextMsg : public cControl {
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
|
||||
@@ -443,6 +443,137 @@ void cPict::advanceAnim() {
|
||||
if(animFrame >= 256) animFrame = 0;
|
||||
}
|
||||
|
||||
std::string cPict::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
std::string name, id;
|
||||
ePicType type;
|
||||
bool wide = false, tall = false, custom = false, tiny = false;
|
||||
bool foundTop = false, foundLeft = false, foundType = false, foundNum = false; // required attributes
|
||||
rectangle frame;
|
||||
int width = 0, height = 0;
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
else if(name == "type"){
|
||||
std::string val;
|
||||
foundType = true;
|
||||
attr->GetValue(&val);
|
||||
if(val == "blank"){
|
||||
setPict(cPict::BLANK, PIC_TER);
|
||||
foundNum = true;
|
||||
continue;
|
||||
}else if(val == "ter")
|
||||
type = PIC_TER;
|
||||
else if(val == "teranim")
|
||||
type = PIC_TER_ANIM;
|
||||
else if(val == "monst")
|
||||
type = PIC_MONST;
|
||||
else if(val == "dlog")
|
||||
type = PIC_DLOG;
|
||||
else if(val == "talk")
|
||||
type = PIC_TALK;
|
||||
else if(val == "scen")
|
||||
type = PIC_SCEN;
|
||||
else if(val == "item")
|
||||
type = PIC_ITEM;
|
||||
else if(val == "pc")
|
||||
type = PIC_PC;
|
||||
else if(val == "field")
|
||||
type = PIC_FIELD;
|
||||
else if(val == "boom")
|
||||
type = PIC_BOOM;
|
||||
else if(val == "missile")
|
||||
type = PIC_MISSILE;
|
||||
else if(val == "full")
|
||||
type = PIC_FULL;
|
||||
else if(val == "map")
|
||||
type = PIC_TER_MAP;
|
||||
else if(val == "status")
|
||||
type = PIC_STATUS;
|
||||
else throw xBadVal("pict",name,val,attr->Row(),attr->Column(),fname);
|
||||
if(foundNum) {
|
||||
pic_num_t wasPic = getPicNum();
|
||||
setPict(wasPic, type);
|
||||
}
|
||||
}else if(name == "custom"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") custom = true;
|
||||
}else if(name == "scaled"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_WRAP, false);
|
||||
}else if(name == "size"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "wide") wide = true;
|
||||
else if(val == "tall") tall = true;
|
||||
else if(val == "large") wide = tall = true;
|
||||
else if(val == "small") tiny = true;
|
||||
else throw xBadVal("pict",name,val,attr->Row(),attr->Column(),fname);
|
||||
}else if(name == "def-key"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
// TODO: The modifiers are now in key-mod, so this needs to be updated
|
||||
try{
|
||||
attachKey(parseKey(val));
|
||||
}catch(int){
|
||||
throw xBadVal("pict",name,val,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
}else if(name == "num"){
|
||||
pic_num_t newPic;
|
||||
attr->GetValue(&newPic), foundNum = true;
|
||||
if(foundType) setPict(newPic, type);
|
||||
else setPict(newPic);
|
||||
}else if(name == "top"){
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
}else if(name == "left"){
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
}else if(name == "width"){
|
||||
attr->GetValue(&width);
|
||||
}else if(name == "height"){
|
||||
attr->GetValue(&height);
|
||||
}else if(name == "framed"){
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_FRAME, true);
|
||||
else setFormat(TXT_FRAME, false);
|
||||
}else throw xBadAttr("pict",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundType) throw xMissingAttr("pict","type",who.Row(),who.Column(),fname);
|
||||
if(!foundNum) throw xMissingAttr("pict","num",who.Row(),who.Column(),fname);
|
||||
if(!foundTop) throw xMissingAttr("pict","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("pict","left",who.Row(),who.Column(),fname);
|
||||
if(wide || tall) {
|
||||
pic_num_t wasPic = getPicNum();
|
||||
if(wide && !tall && getPicType() == PIC_MONST) setPict(wasPic, PIC_MONST_WIDE);
|
||||
else if(!wide && tall && getPicType() == PIC_MONST) setPict(wasPic, PIC_MONST_TALL);
|
||||
else if(wide && tall){
|
||||
if(getPicType() == PIC_MONST) setPict(wasPic, PIC_MONST_LG);
|
||||
else if(getPicType() == PIC_SCEN) setPict(wasPic, PIC_SCEN_LG);
|
||||
else if(getPicType() == PIC_DLOG) setPict(wasPic, PIC_DLOG_LG);
|
||||
}
|
||||
} else if(tiny && type == PIC_ITEM) {
|
||||
pic_num_t wasPic = getPicNum();
|
||||
setPict(wasPic, PIC_TINY_ITEM);
|
||||
}
|
||||
frame.right = frame.left;
|
||||
frame.bottom = frame.top;
|
||||
if(width > 0 || height > 0 || getPicType() == PIC_FULL){
|
||||
frame.right = frame.left + width;
|
||||
frame.bottom = frame.top + height;
|
||||
}
|
||||
setBounds(frame);
|
||||
pic_num_t wasPic = getPicNum();
|
||||
if(custom) {
|
||||
setPict(wasPic, getPicType() + PIC_CUSTOM);
|
||||
} else setPict(wasPic, getPicType());
|
||||
// The above line also sets the graphic's bounding rect, if necessary
|
||||
return id;
|
||||
}
|
||||
|
||||
void cPict::recalcRect() {
|
||||
rectangle bounds = getBounds();
|
||||
switch(picType) {
|
||||
|
||||
@@ -25,6 +25,7 @@ class cPict : public cControl {
|
||||
public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
|
||||
@@ -201,6 +201,12 @@ void cScrollbar::draw() {
|
||||
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
||||
}
|
||||
|
||||
std::string cScrollbar::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
// TODO: Parse scrollbars
|
||||
return "";
|
||||
}
|
||||
|
||||
cControl::storage_t cScrollbar::store() {
|
||||
storage_t storage = cControl::store();
|
||||
storage["scroll-pos"] = pos;
|
||||
|
||||
@@ -32,6 +32,7 @@ class cScrollbar : public cControl {
|
||||
public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
/// Create a new scrollbar without a parent dialog.
|
||||
/// @param parent The parent window.
|
||||
explicit cScrollbar(sf::RenderWindow& parent);
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
#include "stack.hpp"
|
||||
#include "field.hpp"
|
||||
#include "button.hpp"
|
||||
#include "message.hpp"
|
||||
#include "pict.hpp"
|
||||
|
||||
void cStack::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) {
|
||||
onClick = f;
|
||||
@@ -151,3 +154,59 @@ void cStack::fillTabOrder(std::vector<int>& specificTabs, std::vector<int>& reve
|
||||
|
||||
cStack::cStack(cDialog& parent) : cControl(CTRL_STACK, parent), curPage(0), nPages(0) {}
|
||||
|
||||
std::string cStack::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Element> node;
|
||||
std::string name, id;
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++) {
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
else if(name == "pages") {
|
||||
size_t val;
|
||||
attr->GetValue(&val);
|
||||
setPageCount(val);
|
||||
} else throw xBadAttr("stack",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
std::vector<std::string> stack;
|
||||
for(node = node.begin(&who); node != node.end(); node++) {
|
||||
std::string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::ELEMENT) {
|
||||
if(val == "field") {
|
||||
auto field = parent->parse<cTextField>(*node);
|
||||
parent->add(field.second, field.second->getBounds(), field.first);
|
||||
stack.push_back(field.first);
|
||||
// TODO: Add field to tab order
|
||||
//tabOrder.push_back(field);
|
||||
} else if(val == "text") {
|
||||
auto text = parent->parse<cTextMsg>(*node);
|
||||
parent->add(text.second, text.second->getBounds(), text.first);
|
||||
stack.push_back(text.first);
|
||||
} else if(val == "pict") {
|
||||
auto pict = parent->parse<cPict>(*node);
|
||||
parent->add(pict.second, pict.second->getBounds(), pict.first);
|
||||
stack.push_back(pict.first);
|
||||
} else if(val == "button") {
|
||||
auto button = parent->parse<cButton>(*node);
|
||||
parent->add(button.second, button.second->getBounds(), button.first);
|
||||
stack.push_back(button.first);
|
||||
} else if(val == "led") {
|
||||
auto led = parent->parse<cLed>(*node);
|
||||
parent->add(led.second, led.second->getBounds(), led.first);
|
||||
stack.push_back(led.first);
|
||||
} else if(val == "group") {
|
||||
auto group = parent->parse<cLedGroup>(*node);
|
||||
parent->add(group.second, group.second->getBounds(), group.first);
|
||||
stack.push_back(group.first);
|
||||
} else throw xBadNode(val,node->Row(),node->Column(),fname);
|
||||
} else if(type != TiXmlNode::COMMENT)
|
||||
throw xBadVal("stack",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
controls = stack;
|
||||
recalcRect();
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ class cStack : public cControl {
|
||||
std::vector<std::string> controls;
|
||||
click_callback_t onClick;
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
|
||||
Reference in New Issue
Block a user