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("button",name,attr->Row(),attr->Column()); } 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 == "led"){ p.second->choices.insert(parse<cLed>(*node)); }else{ val = '<' + val + '>'; throw xBadVal("text","<content>", content + val,node->Row(),node->Column()); } } p.second->lbl = content; p.second->recalcRect(); if(p.first == ""){ do{ p.first = generateRandomString(); }while(controls.find(p.first) != controls.end()); } return p; }
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; }
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 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 == "num") p.second->isNumericField = true; else if(val == "text") p.second->isNumericField = false; else throw xBadVal("field",name,val,attr->Row(),attr->Column()); }else if(name == "top"){ attr->GetValue(&p.second->frame.top), foundTop = true; }else if(name == "left"){ attr->GetValue(&p.second->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()); } if(!foundTop) throw xMissingAttr("field","top",attr->Row(),attr->Column()); if(!foundLeft) throw xMissingAttr("field","left",attr->Row(),attr->Column()); p.second->frame.right = p.second->frame.left + width; p.second->frame.bottom = p.second->frame.top + height; if(p.first == ""){ do{ p.first = generateRandomString(); }while(controls.find(p.first) != controls.end()); } return p; }
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 if(name == "framed"){ std::string val; attr->GetValue(&val); if(val == "true") setFormat(TXT_FRAME, true); }else if(name == "outline") { std::string val; attr->GetValue(&val); if(val == "solid") setFormat(TXT_FRAMESTYLE, FRM_SOLID); else if(val == "inset") setFormat(TXT_FRAMESTYLE, FRM_INSET); else if(val == "outset") setFormat(TXT_FRAMESTYLE, FRM_OUTSET); else if(val == "double") setFormat(TXT_FRAMESTYLE, FRM_DOUBLE); }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; }
void cDialog::loadFromFile(std::string path){ char cPath[512]; UniChar* ucpath = new UniChar[path.length()]; for(unsigned int i = 0; i < path.length(); i++) ucpath[i] = path[i]; CFBundleRef mainBundle=CFBundleGetMainBundle(); CFURLRef url = CFBundleCopyResourceURL( mainBundle, CFStringCreateWithCharacters(NULL, ucpath, path.length()), CFSTR(""), CFSTR("dialogs") ); delete ucpath; CFStringRef cfpath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); CFStringGetCString(cfpath, cPath, 512, kCFStringEncodingUTF8); try{ printf("Loading dialog from: %s\n", cPath); Document xml(cPath); xml.LoadFile(); Iterator<Attribute> attr; Iterator<Element> node; string type, name, val; xml.FirstChildElement()->GetValue(&type); if(type != "dialog") throw xBadNode(type,xml.FirstChildElement()->Row(),xml.FirstChildElement()->Column()); for(attr = attr.begin(xml.FirstChildElement()); attr != attr.end(); attr++){ attr->GetName(&name); attr->GetValue(&val); if(name == "skin"){ if(val == "light") bg = BG_LIGHT; else if(val == "dark") bg = BG_DARK; else{ istringstream sin(val); sin >> bg; if(sin.fail()) throw xBadVal(type,name,val,attr->Row(),attr->Column()); } }else if(name == "fore"){ RGBColor clr; try{ clr = parseColor(val); }catch(int){ throw xBadVal("text",name,val,attr->Row(),attr->Column()); } defTextClr = clr; }else if(name != "debug") throw xBadAttr(type,name,attr->Row(),attr->Column()); } for(node = node.begin(xml.FirstChildElement()); node != node.end(); node++){ node->GetValue(&type); // Yes, I'm using insert instead of [] to add elements to the map. // In this situation, it's actually easier that way; the reason being, the // map key is obtained from the name attribute of each element. if(type == "field") controls.insert(parse<cTextField>(*node)); else if(type == "text") controls.insert(parse<cTextMsg>(*node)); else if(type == "pict") controls.insert(parse<cPict>(*node)); else if(type == "button") controls.insert(parse<cButton>(*node)); else if(type == "led") controls.insert(parse<cLed>(*node)); else if(type == "group") controls.insert(parse<cLedGroup>(*node)); else throw xBadNode(type,node->Row(),node->Column()); } } catch(Exception& x){ // XML processing exception
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 p.second = new cLed(this); p.second->type = BTN_LED; 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->state = led_red; else if(val == "green") p.second->state = led_green; else if(val == "off") p.second->state = led_off; else throw xBadVal("led",name,val,attr->Row(),attr->Column()); }else if(name == "fromlist") attr->GetValue(&p.second->fromList); else if(name == "font"){ std::string val; attr->GetValue(&val); if(val == "dungeon") p.second->textFont = DUNGEON; else if(val == "geneva") p.second->textFont = GENEVA; else if(val == "silom") p.second->textFont = SILOM; else if(val == "maidenword") p.second->textFont = MAIDENWORD; else throw xBadVal("text",name,val,attr->Row(),attr->Column()); }else if(name == "size"){ std::string val; attr->GetValue(&val); if(val == "large") p.second->textSize = 12; else if(val == "small") p.second->textSize = 10; else throw xBadVal("text",name,val,attr->Row(),attr->Column()); }else if(name == "color" || name == "colour"){ std::string val; attr->GetValue(&val); RGBColor clr; try{ clr = parseColor(val); }catch(int){ throw xBadVal("text",name,val,attr->Row(),attr->Column()); } p.second->color = clr; }else if(name == "top"){ attr->GetValue(&p.second->frame.top), foundTop = true; }else if(name == "left"){ attr->GetValue(&p.second->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()); } if(!foundTop) throw xMissingAttr("led","top",who.Row(),who.Column()); if(!foundLeft) throw xMissingAttr("led","left",who.Row(),who.Column()); if(width > 0 || height > 0) { p.second->frame.right = p.second->frame.left + width; p.second->frame.bottom = p.second->frame.top + height; }else{ p.second->frame.right = p.second->frame.left + 14; p.second->frame.bottom = p.second->frame.top + 10; } 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 += val; else{ val = '<' + val + '>'; throw xBadVal("text","<content>",content + val,node->Row(),node->Column()); } } p.second->lbl = content; if(p.first == ""){ do{ p.first = generateRandomString(); }while(controls.find(p.first) != controls.end()); } return p; }
template<> pair<string,cPict*> cDialog::parse(Element& who /*pict*/){ std::pair<std::string,cPict*> p; Iterator<Attribute> attr; std::string name; bool wide = false, tall = false, custom = false; bool foundTop = false, foundLeft = false, foundType = false, foundNum = false; // required attributes 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->picType = PIC_TER; p.second->picNum = -1; }else if(val == "ter") p.second->picType = PIC_TER; else if(val == "teranim") p.second->picType = PIC_TER_ANIM; else if(val == "monst") p.second->picType = PIC_MONST; else if(val == "dlog") p.second->picType = PIC_DLOG; else if(val == "talk") p.second->picType = PIC_TALK; else if(val == "scen") p.second->picType = PIC_SCEN; else if(val == "item") p.second->picType = PIC_ITEM; else if(val == "pc") p.second->picType = PIC_PC; else if(val == "field") p.second->picType = PIC_FIELD; else if(val == "boom") p.second->picType = PIC_BOOM; else if(val == "missile") p.second->picType = PIC_MISSILE; else if(val == "full") p.second->picType = PIC_FULL; else if(val == "map") p.second->picType = PIC_TER_MAP; else if(val == "status") p.second->picType = PIC_STATUS; else throw xBadVal("pict",name,val,attr->Row(),attr->Column()); }else if(name == "custom"){ std::string val; attr->GetValue(&val); if(val == "true") custom = true; }else if(name == "clickable"){ std::string val; attr->GetValue(&val); if(val == "true") p.second->clickable = true; }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 throw xBadVal("pict",name,val,attr->Row(),attr->Column()); }else if(name == "def-key"){ std::string val; attr->GetValue(&val); try{ p.second->key = parseKey(val); }catch(int){ throw xBadVal("pict",name,val,attr->Row(),attr->Column()); } }else if(name == "num"){ attr->GetValue(&p.second->picNum), foundNum = true; }else if(name == "top"){ attr->GetValue(&p.second->frame.top), foundTop = true; }else if(name == "left"){ attr->GetValue(&p.second->frame.left), foundLeft = true;; }else if(name == "width"){ attr->GetValue(&width); }else if(name == "height"){ attr->GetValue(&height); }else throw xBadAttr("pict",name,attr->Row(),attr->Column()); } if(!foundType) throw xMissingAttr("pict","type",who.Row(),who.Column()); if(!foundNum) throw xMissingAttr("pict","num",who.Row(),who.Column()); if(!foundTop) throw xMissingAttr("pict","top",who.Row(),who.Column()); if(!foundLeft) throw xMissingAttr("pict","left",who.Row(),who.Column()); if(wide && !tall && p.second->picType == PIC_MONST) p.second->picType = PIC_MONST_WIDE; else if(!wide && tall && p.second->picType == PIC_MONST) p.second->picType = PIC_MONST_TALL; else if(wide && tall){ if(p.second->picType == PIC_MONST) p.second->picType = PIC_MONST_LG; else if(p.second->picType == PIC_SCEN) p.second->picType = PIC_SCEN_LG; else if(p.second->picType == PIC_DLOG) p.second->picType = PIC_DLOG_LG; } p.second->frame.right = p.second->frame.left; p.second->frame.bottom = p.second->frame.top; if(width > 0 || height > 0 || p.second->picType == PIC_FULL){ p.second->frame.right = p.second->frame.left + width; p.second->frame.bottom = p.second->frame.top + height; }else switch(p.second->picType){ case PIC_DLOG: p.second->frame.right = p.second->frame.left + 36; p.second->frame.bottom = p.second->frame.top + 36; break; case PIC_DLOG_LG: p.second->frame.right = p.second->frame.left + 72; p.second->frame.bottom = p.second->frame.top + 72; break; case PIC_SCEN: case PIC_TALK: p.second->frame.right = p.second->frame.left + 32; p.second->frame.bottom = p.second->frame.top + 32; break; case PIC_SCEN_LG: p.second->frame.right = p.second->frame.left + 64; p.second->frame.bottom = p.second->frame.top + 64; break; case PIC_MISSILE: p.second->frame.right = p.second->frame.left + 18; p.second->frame.bottom = p.second->frame.top + 18; break; case PIC_TER_MAP: p.second->frame.right = p.second->frame.left + 24; p.second->frame.bottom = p.second->frame.top + 24; break; case PIC_STATUS: p.second->frame.right = p.second->frame.left + 12; p.second->frame.bottom = p.second->frame.top + 12; break; default: p.second->frame.right = p.second->frame.left + 28; p.second->frame.bottom = p.second->frame.top + 36; break; } if(custom) p.second->picType += PIC_CUSTOM; if(p.first == ""){ do{ p.first = generateRandomString(); }while(controls.find(p.first) != controls.end()); } return p; }
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 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->wrapLabel = true; }else if(name == "type"){ std::string val; foundType = true; attr->GetValue(&val); if(val == "small") p.second->type = BTN_SM; else if(val == "regular") p.second->type = BTN_REG; else if(val == "large") p.second->type = BTN_LG; else if(val == "help") p.second->type = BTN_HELP; else if(val == "left") p.second->type = BTN_LEFT; else if(val == "right") p.second->type = BTN_RIGHT; else if(val == "up") p.second->type = BTN_UP; else if(val == "down") p.second->type = BTN_DOWN; else if(val == "tiny") p.second->type = BTN_TINY; else if(val == "done") p.second->type = BTN_DONE; else if(val == "tall") p.second->type = BTN_TALL; else if(val == "trait") p.second->type = BTN_TRAIT; else if(val == "push") p.second->type = BTN_PUSH; }else if(name == "def-key"){ std::string val; attr->GetValue(&val); try{ p.second->key = parseKey(val); }catch(int){ throw xBadVal("button",name,val,attr->Row(),attr->Column()); } }else if(name == "fromlist") attr->GetValue(&p.second->fromList); else if(name == "top"){ attr->GetValue(&p.second->frame.top), foundTop = true; }else if(name == "left"){ attr->GetValue(&p.second->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()); } if(!foundType) throw xMissingAttr("button","type",who.Row(),who.Column()); if(!foundTop) throw xMissingAttr("button","top",who.Row(),who.Column()); if(!foundLeft) throw xMissingAttr("button","left",who.Row(),who.Column()); if(width > 0 || height > 0) { p.second->frame.right = p.second->frame.left + width; p.second->frame.bottom = p.second->frame.top + height; }else switch(p.second->type){ case BTN_SM: p.second->frame.right = p.second->frame.left + 23; p.second->frame.bottom = p.second->frame.top + 23; break; case BTN_LG: p.second->frame.right = p.second->frame.left + 102; p.second->frame.bottom = p.second->frame.top + 23; break; case BTN_HELP: p.second->frame.right = p.second->frame.left + 16; p.second->frame.bottom = p.second->frame.top + 13; break; case BTN_TINY: case BTN_LED: // this should never happen p.second->frame.right = p.second->frame.left + 14; p.second->frame.bottom = p.second->frame.top + 10; break; case BTN_TALL: case BTN_TRAIT: p.second->frame.right = p.second->frame.left + 63; p.second->frame.bottom = p.second->frame.top + 40; break; case BTN_PUSH: p.second->frame.right = p.second->frame.left + 30; p.second->frame.bottom = p.second->frame.top + 30; break; default: p.second->frame.right = p.second->frame.left + 63; p.second->frame.bottom = p.second->frame.top + 23; } 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"){ if(content.length() > 0) throw xBadVal("button","<content>",content + val,node->Row(),node->Column()); p.second->labelWithKey = true; }else if(type == TiXmlNode::TEXT) content += val; else{ val = '<' + val + '>'; throw xBadVal("text","<content>",val,node->Row(),node->Column()); } } p.second->lbl = content; if(p.first == ""){ do{ p.first = generateRandomString(); }while(controls.find(p.first) != controls.end()); } return p; }
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 p.second = new cTextMsg(this); 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->drawFramed = true; }else if(name == "clickable"){ std::string val; attr->GetValue(&val); if(val == "true") p.second->clickable = true; }else if(name == "font"){ std::string val; attr->GetValue(&val); if(val == "dungeon") p.second->textFont = DUNGEON; else if(val == "geneva") p.second->textFont = GENEVA; else if(val == "silom") p.second->textFont = SILOM; else if(val == "maidenword") p.second->textFont = MAIDENWORD; else throw xBadVal("text",name,val,attr->Row(),attr->Column()); }else if(name == "size"){ std::string val; attr->GetValue(&val); if(val == "large") p.second->textSize = 12; else if(val == "small") p.second->textSize = 10; else throw xBadVal("text",name,val,attr->Row(),attr->Column()); }else if(name == "color" || name == "colour"){ std::string val; attr->GetValue(&val); RGBColor clr; try{ clr = parseColor(val); }catch(int){ throw xBadVal("text",name,val,attr->Row(),attr->Column()); } p.second->color = clr; }else if(name == "def-key"){ std::string val; attr->GetValue(&val); try{ p.second->key = parseKey(val); }catch(int){ throw xBadVal("text",name,val,attr->Row(),attr->Column()); } }else if(name == "top"){ attr->GetValue(&p.second->frame.top), foundTop = true; }else if(name == "left"){ attr->GetValue(&p.second->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("pict",name,attr->Row(),attr->Column()); } if(!foundTop) throw xMissingAttr("text","top",who.Row(),who.Column()); if(!foundLeft) throw xMissingAttr("text","left",who.Row(),who.Column()); p.second->frame.right = p.second->frame.left + width; p.second->frame.bottom = p.second->frame.top + height; 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 == "br") content += '|'; // because vertical bar is replaced by a newline when drawing strings else if(type == TiXmlNode::TEXT) content += val; else{ val = '<' + val + '>'; throw xBadVal("text","<content>",content + val,node->Row(),node->Column()); } } p.second->lbl = content; if(p.first == ""){ do{ p.first = generateRandomString(); }while(controls.find(p.first) != controls.end()); } return p; }
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; }
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 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"){ std::string val; attr->GetValue(&val); try{ attachKey(parseKey(val)); }catch(int){ throw xBadVal("button",name,val,attr->Row(),attr->Column(),fname); } // }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 || getBtnType() == BTN_PUSH)) 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); 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; }
std::string cScrollPane::parse(ticpp::Element& who, std::string fname) { using namespace ticpp; Iterator<Attribute> attr; Iterator<Element> node; std::string name, id; rectangle frame; int width = 0, height = 0; bool foundTop = false, foundLeft = false; scroll.setStyle(SCROLL_LED); for(attr = attr.begin(&who); attr != attr.end(); attr++) { attr->GetName(&name); if(name == "name") attr->GetValue(&id); 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 if(name == "outline") { std::string val; attr->GetValue(&val); if(val == "solid") setFormat(TXT_FRAMESTYLE, FRM_SOLID); else if(val == "inset") setFormat(TXT_FRAMESTYLE, FRM_INSET); else if(val == "outset") setFormat(TXT_FRAMESTYLE, FRM_OUTSET); else if(val == "double") setFormat(TXT_FRAMESTYLE, FRM_DOUBLE); }else if(name == "style"){ std::string val; attr->GetValue(&val); if(val == "white") setStyle(SCROLL_WHITE); else if(val == "led") setStyle(SCROLL_LED); else throw xBadVal("slider", name, val, attr->Row(), attr->Column(), fname); } else throw xBadAttr("pane",name,attr->Row(),attr->Column(),fname); } if(!foundTop) throw xMissingAttr("pane","top",who.Row(),who.Column(),fname); if(!foundLeft) throw xMissingAttr("pane","left",who.Row(),who.Column(),fname); if(width > 0) { frame.width() = width; }else{ throw xMissingAttr("pane","width",who.Row(),who.Column(),fname); } if(height > 0) { frame.height() = height; }else{ frame.height() = 10; } setBounds(frame); 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); contents.insert(field); // TODO: Add field to tab order //tabOrder.push_back(field); } else if(val == "text") { auto text = parent->parse<cTextMsg>(*node); contents.insert(text); } else if(val == "pict") { auto pict = parent->parse<cPict>(*node); contents.insert(pict); } else if(val == "slider") { auto slide = parent->parse<cScrollbar>(*node); contents.insert(slide); } else if(val == "button") { auto button = parent->parse<cButton>(*node); contents.insert(button); } else if(val == "led") { auto led = parent->parse<cLed>(*node); contents.insert(led); } else if(val == "group") { auto group = parent->parse<cLedGroup>(*node); contents.insert(group); } else throw xBadNode(val,node->Row(),node->Column(),fname); } else if(type != TiXmlNode::COMMENT) throw xBadVal("pane",xBadVal::CONTENT,val,node->Row(),node->Column(),fname); } recalcRect(); return id; }
std::string cScrollbar::parse(ticpp::Element& who, std::string fname) { using namespace ticpp; Iterator<Attribute> attr; std::string name, id; bool foundTop = false, foundLeft = false, foundMax = false; // required attributes bool foundVertical = false; rectangle frame; int width = 0, height = 0; style = SCROLL_LED; // Dialog scrollbars have a different default. for(attr = attr.begin(&who); attr != attr.end(); attr++){ attr->GetName(&name); if(name == "name") attr->GetValue(&id); else if(name == "vertical"){ std::string val; attr->GetValue(&val); if(val == "true") vert = true; else vert = false; foundVertical = true; }else if(name == "style"){ std::string val; attr->GetValue(&val); if(val == "white") style = SCROLL_WHITE; else if(val == "led") style = SCROLL_LED; else throw xBadVal("slider", name, val, attr->Row(), attr->Column(), fname); }else if(name == "link"){ attr->GetValue(&link); }else if(name == "initial"){ attr->GetValue(&pos); }else if(name == "max"){ attr->GetValue(&max); foundMax = true; }else if(name == "page-size"){ attr->GetValue(&pgsz); }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("slider",name,attr->Row(),attr->Column(),fname); } if(!foundMax) throw xMissingAttr("slider","num",who.Row(),who.Column(),fname); if(!foundTop) throw xMissingAttr("slider","top",who.Row(),who.Column(),fname); if(!foundLeft) throw xMissingAttr("slider","left",who.Row(),who.Column(),fname); if(pos > max) throw xBadAttr("slider","initial",who.Row(),who.Column(),fname); int thickness = vert ? up_rect[style][VERT].width() : up_rect[style][HORZ].height(); if(width > 0) { frame.right = frame.left + width; if(height == 0 && !foundVertical) vert = false; }else{ if(vert) frame.width() = thickness; else frame.width() = 25; } if(height > 0) { frame.bottom = frame.top + height; if(width == 0 && !foundVertical) vert = true; }else{ frame.bottom = frame.top + 10; if(vert) frame.height() = 25; else frame.height() = thickness; } setBounds(frame); if(parent->hasControl(link)) parent->getControl(link).setTextToNum(pos); return id; }
void cDialog::loadFromFile(std::string path){ static const cKey enterKey = {true, key_enter}; bg = defaultBackground; fname = path; fs::path cPath = progDir/"data"/"dialogs"/path; try{ TiXmlBase::SetCondenseWhiteSpace(false); Document xml(cPath.string().c_str()); xml.LoadFile(); Iterator<Attribute> attr; Iterator<Element> node; string type, name, val, defaultButton; xml.FirstChildElement()->GetValue(&type); if(type != "dialog") throw xBadNode(type,xml.FirstChildElement()->Row(),xml.FirstChildElement()->Column(),fname); for(attr = attr.begin(xml.FirstChildElement()); attr != attr.end(); attr++){ attr->GetName(&name); attr->GetValue(&val); if(name == "skin"){ if(val == "light") bg = BG_LIGHT; else if(val == "dark") bg = BG_DARK; else{ istringstream sin(val); sin >> bg; if(sin.fail()) throw xBadVal(type,name,val,attr->Row(),attr->Column(),fname); } }else if(name == "fore"){ sf::Color clr; try{ clr = cControl::parseColor(val); }catch(int){ throw xBadVal("text",name,val,attr->Row(),attr->Column(),fname); } defTextClr = clr; } else if(name == "defbtn") { defaultButton = val; }else if(name != "debug") throw xBadAttr(type,name,attr->Row(),attr->Column(),fname); } vector<int> specificTabs, reverseTabs; for(node = node.begin(xml.FirstChildElement()); node != node.end(); node++){ node->GetValue(&type); // Yes, I'm using insert instead of [] to add elements to the map. // In this situation, it's actually easier that way; the reason being, the // map key is obtained from the name attribute of each element. if(type == "field") { auto field = parse<cTextField>(*node); controls.insert(field); tabOrder.push_back(field); if(field.second->tabOrder > 0) specificTabs.push_back(field.second->tabOrder); else if(field.second->tabOrder < 0) reverseTabs.push_back(field.second->tabOrder); } else if(type == "text") controls.insert(parse<cTextMsg>(*node)); else if(type == "pict") controls.insert(parse<cPict>(*node)); else if(type == "slider") controls.insert(parse<cScrollbar>(*node)); else if(type == "button") controls.insert(parse<cButton>(*node)); else if(type == "led") controls.insert(parse<cLed>(*node)); else if(type == "group") controls.insert(parse<cLedGroup>(*node)); else if(type == "stack") { auto parsed = parse<cStack>(*node); controls.insert(parsed); // Now, if it contains any fields, their tab order must be accounted for parsed.second->fillTabOrder(specificTabs, reverseTabs); } else if(type == "pane") { auto parsed = parse<cScrollPane>(*node); controls.insert(parsed); // TODO: Now, if it contains any fields, their tab order must be accounted for //parsed.second->fillTabOrder(specificTabs, reverseTabs); } else throw xBadNode(type,node->Row(),node->Column(),fname); } // Set the default button. if(hasControl(defaultButton)) getControl(defaultButton).attachKey(enterKey); // Sort by tab order // First, fill any gaps that might have been left, using ones that had no specific tab order // Of course, if there are not enough without a specific tab order, there could still be gaps using fld_t = decltype(tabOrder)::value_type; auto noTabOrder = [](fld_t x) {return x.second->tabOrder == 0;}; if(!specificTabs.empty()) { int max = *max_element(specificTabs.begin(), specificTabs.end()); for(int i = 1; i < max; i++) { auto check = find(specificTabs.begin(), specificTabs.end(), i); if(check != specificTabs.end()) continue; auto change = find_if(tabOrder.begin(), tabOrder.end(), noTabOrder); if(change == tabOrder.end()) break; change->second->tabOrder = i; } } if(!reverseTabs.empty()) { int max = -*min_element(reverseTabs.begin(), reverseTabs.end()); for(int i = 1; i < max; i++) { auto check = find(reverseTabs.begin(), reverseTabs.end(), -i); if(check != reverseTabs.end()) continue; auto change = find_if(tabOrder.begin(), tabOrder.end(), noTabOrder); if(change == tabOrder.end()) break; change->second->tabOrder = -i; } } // Then, sort - first, positive tab order ascending; then zeros; then negative tab order descending. stable_sort(tabOrder.begin(), tabOrder.end(), [](fld_t a, fld_t b) -> bool { bool a_neg = a.second->tabOrder < 0, b_neg = b.second->tabOrder < 0; if(a_neg && !b_neg) return false; else if(!a_neg && b_neg) return true; bool a_pos = a.second->tabOrder > 0, b_pos = b.second->tabOrder > 0; if(a_pos && !b_pos) return true; else if(!a_pos && b_pos) return false; return a.second->tabOrder < b.second->tabOrder; }); } catch(Exception& x){ // XML processing exception