Refactor dialog parsing to reduce code duplication
- Refactor dialog format parameter management to use a single protected control function - Format parameters "frame" and "frame style" merged - Colour is now a first-class format parameter (though it still has a separate setter)
This commit is contained in:
@@ -226,17 +226,17 @@ private:
|
||||
friend class cControl;
|
||||
};
|
||||
|
||||
/// Thrown when an invalid element is found while parsing an XML dialog definition.
|
||||
/// Thrown when an invalid node (element or text/cdata) is found while parsing an XML dialog definition.
|
||||
class xBadNode : public std::exception {
|
||||
std::string type, dlg;
|
||||
int row, col;
|
||||
mutable const char* msg;
|
||||
public:
|
||||
/// Construct a new exception.
|
||||
/// @param t The tag name of the invalid element.
|
||||
/// @param r The line number of the element in the source.
|
||||
/// @param c The column number of the element in the source.
|
||||
/// @param dlg The name of the file in which the element occurred.
|
||||
/// @param t The tag name of the invalid element, or empty if the invalid node was a text node.
|
||||
/// @param r The line number of the node in the source.
|
||||
/// @param c The column number of the node in the source.
|
||||
/// @param dlg The name of the file in which the node occurred.
|
||||
xBadNode(std::string t, int r, int c, std::string dlg) throw();
|
||||
~xBadNode() throw();
|
||||
/// @return The error message.
|
||||
|
||||
@@ -90,161 +90,89 @@ void cButton::draw(){
|
||||
}
|
||||
}
|
||||
|
||||
void cButton::setFormat(eFormat prop, short val){
|
||||
if(prop == TXT_WRAP) wrapLabel = val;
|
||||
else if(prop == TXT_FRAMESTYLE) frameStyle = eFrameStyle(val);
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cButton::getFormat(eFormat prop){
|
||||
if(prop == TXT_WRAP) return wrapLabel;
|
||||
else if(prop == TXT_FRAMESTYLE) return frameStyle;
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
void cButton::setColour(sf::Color clr) {
|
||||
textClr = clr;
|
||||
}
|
||||
|
||||
sf::Color cButton::getColour() {
|
||||
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
|
||||
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);
|
||||
bool cButton::manageFormat(eFormat prop, bool set, boost::any* val) {
|
||||
switch(prop) {
|
||||
case TXT_FRAME:
|
||||
if(val) {
|
||||
if(set) frameStyle = boost::any_cast<eFrameStyle>(*val);
|
||||
else *val = frameStyle;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
case TXT_WRAP:
|
||||
if(val) {
|
||||
if(set) wrapLabel = boost::any_cast<bool>(*val);
|
||||
else *val = wrapLabel;
|
||||
}
|
||||
// }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);
|
||||
break;
|
||||
case TXT_COLOUR:
|
||||
if(val) {
|
||||
if(set) textClr = boost::any_cast<sf::Color>(*val);
|
||||
else *val = textClr;
|
||||
}
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cButton::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
std::string name = attr.Name();
|
||||
if(name == "type") {
|
||||
std::string val = attr.Value();
|
||||
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_DONE);
|
||||
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 throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
} else if(name == "def-key") {
|
||||
std::string val = attr.Value();
|
||||
try {
|
||||
attachKey(parseKey(val));
|
||||
} catch(int) {
|
||||
throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
setText(content);
|
||||
return id;
|
||||
return cControl::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
bool cButton::parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) {
|
||||
if(content.Type() == TiXmlNode::TEXT) {
|
||||
text += dlogStringFilter(content.Value());
|
||||
return true;
|
||||
} else if(content.Value() == "key") {
|
||||
// TODO: There's surely a better way to do this
|
||||
if(text.length() > 0) throw xBadVal("button", xBadVal::CONTENT, text + "<key/>", content.Row(), content.Column(), fname);
|
||||
labelWithKey = true;
|
||||
return true;
|
||||
}
|
||||
return cControl::parseContent(content, n, tagName, fname, text);
|
||||
}
|
||||
|
||||
void cButton::validatePostParse(ticpp::Element& elem, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& elems) {
|
||||
cControl::validatePostParse(elem, fname, attrs, elems);
|
||||
if(getType() == CTRL_BTN && !attrs.count("type")) throw xMissingAttr(elem.Value(), "type", elem.Row(), elem.Column(), fname);
|
||||
static const std::set<eBtnType> labelledButtons{BTN_TINY, BTN_LED, BTN_PUSH};
|
||||
if(labelledButtons.count(type)) {
|
||||
if(!attrs.count("color") && !attrs.count("colour") && parent->getBg() == cDialog::BG_DARK)
|
||||
setColour(sf::Color::White);
|
||||
if(!attrs.count("width"))
|
||||
throw xMissingAttr(elem.Value(), "width", elem.Row(), elem.Column(), fname);
|
||||
}
|
||||
}
|
||||
|
||||
location cButton::getPreferredSize() {
|
||||
return {btnRects[type][0].width(), btnRects[type][0].height()};
|
||||
}
|
||||
|
||||
// Indices within the buttons array.
|
||||
@@ -348,18 +276,35 @@ void cLed::callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::str
|
||||
}
|
||||
}
|
||||
|
||||
void cLed::setFormat(eFormat prop, short val){
|
||||
if(prop == TXT_FONT) textFont = (eFont) val;
|
||||
else if(prop == TXT_SIZE) textSize = val;
|
||||
else if(prop == TXT_WRAP) wrapLabel = val;
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cLed::getFormat(eFormat prop){
|
||||
if(prop == TXT_FONT) return textFont;
|
||||
else if(prop == TXT_SIZE) return textSize;
|
||||
else if(prop == TXT_WRAP) return wrapLabel;
|
||||
else throw xUnsupportedProp(prop);
|
||||
bool cLed::manageFormat(eFormat prop, bool set, boost::any* val) {
|
||||
switch(prop) {
|
||||
case TXT_FONT:
|
||||
if(val) {
|
||||
if(set) textFont = boost::any_cast<eFont>(*val);
|
||||
else *val = textFont;
|
||||
}
|
||||
break;
|
||||
case TXT_SIZE:
|
||||
if(val) {
|
||||
if(set) textSize = boost::any_cast<short>(*val);
|
||||
else *val = textSize;
|
||||
}
|
||||
break;
|
||||
case TXT_WRAP:
|
||||
if(val) {
|
||||
if(set) wrapLabel = boost::any_cast<bool>(*val);
|
||||
else *val = wrapLabel;
|
||||
}
|
||||
break;
|
||||
case TXT_COLOUR:
|
||||
if(val) {
|
||||
if(set) textClr = boost::any_cast<sf::Color>(*val);
|
||||
else *val = textClr;
|
||||
}
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cLed::draw(){
|
||||
@@ -439,104 +384,22 @@ 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);
|
||||
bool cLed::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
if(attr.Name() == "state") {
|
||||
std::string val = attr.Value();
|
||||
if(val == "red") setState(led_red);
|
||||
else if(val == "green") setState(led_green);
|
||||
else if(val == "off") setState(led_off);
|
||||
else throw xBadVal(tagName, attr.Name(), val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
return cButton::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
bool cLed::parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) {
|
||||
if(content.Type() == TiXmlNode::ELEMENT && content.Value() == "key")
|
||||
return false;
|
||||
return cButton::parseContent(content, n, tagName, fname, text);
|
||||
}
|
||||
|
||||
void cLedGroup::addChoice(cLed* ctrl, std::string key) {
|
||||
@@ -627,27 +490,6 @@ void cLedGroup::hide(std::string id){
|
||||
choices[id]->hide();
|
||||
}
|
||||
|
||||
void cLedGroup::setFormat(eFormat prop, short val) {
|
||||
if(prop == TXT_FRAME) drawFramed = val;
|
||||
else if(prop == TXT_FRAMESTYLE) frameStyle = eFrameStyle(val);
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cLedGroup::getFormat(eFormat prop) {
|
||||
if(prop == TXT_FRAME) return drawFramed;
|
||||
else if(prop == TXT_FRAMESTYLE) return frameStyle;
|
||||
throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
void cLedGroup::setColour(sf::Color) {
|
||||
// TODO: Colour is not supported
|
||||
}
|
||||
|
||||
sf::Color cLedGroup::getColour() {
|
||||
// TODO: Colour is not supported
|
||||
return sf::Color();
|
||||
}
|
||||
|
||||
bool cLedGroup::isClickable(){
|
||||
return true;
|
||||
}
|
||||
@@ -725,7 +567,7 @@ void cLedGroup::draw(){
|
||||
iter->second->draw();
|
||||
iter++;
|
||||
}
|
||||
if(drawFramed) drawFrame(2, frameStyle);
|
||||
drawFrame(2, frameStyle);
|
||||
}
|
||||
|
||||
void cButton::setBtnType(eBtnType newType){
|
||||
@@ -756,8 +598,8 @@ void cButton::setBtnType(eBtnType newType){
|
||||
frame.height() = 40;
|
||||
break;
|
||||
case BTN_PUSH:
|
||||
frame.width() = 30;
|
||||
frame.height() = 30;
|
||||
frame.width() = std::min<int>(frame.width(), 30);
|
||||
frame.height() = std::min<int>(frame.height(), 30);
|
||||
break;
|
||||
case BTN_TINY:
|
||||
case BTN_LED:
|
||||
@@ -789,42 +631,22 @@ void cLedGroup::forEach(std::function<void(std::string,cControl&)> callback) {
|
||||
callback(ctrl.first, *ctrl.second);
|
||||
}
|
||||
|
||||
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);
|
||||
bool cLedGroup::parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) {
|
||||
std::string val = content.Value();
|
||||
int type = content.Type();
|
||||
if(type == TiXmlNode::ELEMENT && val == "led"){
|
||||
auto led = parent->parse<cLed>(dynamic_cast<ticpp::Element&>(content));
|
||||
addChoice(led.second, led.first);
|
||||
return true;
|
||||
} else if(type == TiXmlNode::TEXT) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
return cContainer::parseContent(content, n, tagName, fname, text);
|
||||
}
|
||||
|
||||
void cLedGroup::validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) {
|
||||
// Don't defer to super-class; groups are an abstract container that doesn't require a position.
|
||||
//cControl::validatePostParse(who, fname, attrs, nodes);
|
||||
recalcRect();
|
||||
frameStyle = FRM_NONE;
|
||||
}
|
||||
|
||||
@@ -50,11 +50,10 @@ class cButton : public cControl {
|
||||
public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void setFormat(eFormat prop, short val);
|
||||
short getFormat(eFormat prop);
|
||||
void setColour(sf::Color clr);
|
||||
sf::Color getColour();
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
|
||||
void validatePostParse(ticpp::Element& elem, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& elems) override;
|
||||
location getPreferredSize() override;
|
||||
/// Set the type of this button.
|
||||
/// @param newType The desired button type.
|
||||
void setBtnType(eBtnType newType);
|
||||
@@ -88,6 +87,7 @@ protected:
|
||||
/// @param t The type of control. Should be either CTRL_LED or CTRL_BTN.
|
||||
cButton(cDialog& parent,eControlType t);
|
||||
private:
|
||||
bool manageFormat(eFormat prop, bool set, boost::any* val) override;
|
||||
bool labelWithKey;
|
||||
std::string fromList;
|
||||
static rectangle btnRects[13][2];
|
||||
@@ -114,9 +114,8 @@ 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) override;
|
||||
void setFormat(eFormat prop, short val) override;
|
||||
short getFormat(eFormat prop) override;
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
|
||||
storage_t store() override;
|
||||
void restore(storage_t to) override;
|
||||
/// Create a new LED button.
|
||||
@@ -141,6 +140,7 @@ public:
|
||||
private:
|
||||
void defaultClickHandler(cDialog&, std::string, eKeyMod);
|
||||
void callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) override;
|
||||
bool manageFormat(eFormat prop, bool set, boost::any* val) override;
|
||||
eLedState state;
|
||||
eFont textFont;
|
||||
short textSize;
|
||||
@@ -166,7 +166,6 @@ private:
|
||||
/// However, when the focus handler of the LED group is called, the selection _has_ been updated.,
|
||||
/// so getSelected() will return the new selection. (This is the reason for the getPreviousSelection() method.)
|
||||
class cLedGroup : public cContainer {
|
||||
bool drawFramed = false;
|
||||
std::map<std::string,cLed*> choices;
|
||||
std::string fromList;
|
||||
std::string curSelect, prevSelect;
|
||||
@@ -177,7 +176,8 @@ class cLedGroup : public cContainer {
|
||||
public:
|
||||
/// @deprecated in favour of @ref attachEventHandler
|
||||
void attachFocusHandler(std::function<bool(cDialog&,std::string,bool)> f) override;
|
||||
std::string parse(ticpp::Element& who, std::string fname) override;
|
||||
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
|
||||
void validatePostParse(ticpp::Element& elem, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& elems) override;
|
||||
/// @copydoc cControl::attachClickHandler()
|
||||
///
|
||||
/// The click handler is called whenever an LED in the group is clicked, even if it's the currently selected LED.
|
||||
@@ -210,10 +210,6 @@ public:
|
||||
/// Show one of the choices in this group.
|
||||
/// @param id The unique key of the choice.
|
||||
void show(std::string id);
|
||||
void setFormat(eFormat prop, short val) override;
|
||||
short getFormat(eFormat prop) override;
|
||||
void setColour(sf::Color clr) override;
|
||||
sf::Color getColour() override;
|
||||
/// Create a new LED group.
|
||||
/// @param parent The parent dialog.
|
||||
explicit cLedGroup(cDialog& parent);
|
||||
|
||||
@@ -67,9 +67,6 @@ const char* xUnsupportedProp::what() const throw(){
|
||||
case TXT_FRAME:
|
||||
s = "TXT_FRAME";
|
||||
break;
|
||||
case TXT_FRAMESTYLE:
|
||||
s = "TXT_FRAMESTYLE";
|
||||
break;
|
||||
case TXT_FONT:
|
||||
s = "TXT_FONT";
|
||||
break;
|
||||
@@ -79,8 +76,10 @@ const char* xUnsupportedProp::what() const throw(){
|
||||
case TXT_WRAP:
|
||||
s = "TXT_WRAP";
|
||||
break;
|
||||
case TXT_COLOUR:
|
||||
s = "TXT_COLOUR";
|
||||
break;
|
||||
}
|
||||
// TODO: Support colour, which doesn't use the setFormat function
|
||||
sprintf(msg,"Format property %s not valid for this control.\n",s.c_str());
|
||||
}
|
||||
return msg;
|
||||
@@ -188,6 +187,69 @@ void cControl::setActive(bool active) {
|
||||
depressed = active;
|
||||
}
|
||||
|
||||
void cControl::setFormat(eFormat prop, short val) {
|
||||
boost::any newVal;
|
||||
switch(prop) {
|
||||
case TXT_WRAP:
|
||||
newVal = bool(val);
|
||||
break;
|
||||
case TXT_FONT:
|
||||
newVal = eFont(val);
|
||||
break;
|
||||
case TXT_SIZE:
|
||||
newVal = val;
|
||||
break;
|
||||
case TXT_FRAME:
|
||||
newVal = eFrameStyle(val);
|
||||
break;
|
||||
case TXT_COLOUR: // Interpret as a shade of grey
|
||||
newVal = sf::Color{val, val, val};
|
||||
break;
|
||||
}
|
||||
if(!manageFormat(prop, true, &newVal))
|
||||
throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cControl::getFormat(eFormat prop) {
|
||||
boost::any curVal;
|
||||
if(!manageFormat(prop, false, &curVal))
|
||||
throw xUnsupportedProp(prop);
|
||||
switch(prop) {
|
||||
case TXT_WRAP:
|
||||
return boost::any_cast<bool>(curVal);
|
||||
case TXT_FONT:
|
||||
return boost::any_cast<eFont>(curVal);
|
||||
case TXT_SIZE:
|
||||
return boost::any_cast<short>(curVal);
|
||||
case TXT_FRAME:
|
||||
return boost::any_cast<eFrameStyle>(curVal);
|
||||
case TXT_COLOUR: // Interpret as a shade of grey
|
||||
return boost::any_cast<sf::Color>(curVal).toInteger();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cControl::canFormat(eFormat prop) {
|
||||
return manageFormat(prop, false, nullptr);
|
||||
}
|
||||
|
||||
void cControl::setColour(sf::Color clr) {
|
||||
boost::any newVal = clr;
|
||||
if(!manageFormat(TXT_COLOUR, true, &newVal))
|
||||
throw xUnsupportedProp(TXT_COLOUR);
|
||||
}
|
||||
|
||||
sf::Color cControl::getColour() {
|
||||
boost::any curVal;
|
||||
if(!manageFormat(TXT_COLOUR, false, &curVal))
|
||||
throw xUnsupportedProp(TXT_COLOUR);
|
||||
return boost::any_cast<sf::Color>(curVal);
|
||||
}
|
||||
|
||||
bool cControl::manageFormat(eFormat, bool, boost::any*) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void cControl::redraw() {
|
||||
// If there's no parent dialog, we're not responsible for redrawing
|
||||
if(parent) parent->draw();
|
||||
@@ -312,6 +374,7 @@ bool cControl::triggerFocusHandler(cDialog& dlg, std::string id, bool losing){
|
||||
}
|
||||
|
||||
void cControl::drawFrame(short amt, eFrameStyle frameStyle){
|
||||
if(frameStyle == FRM_NONE) return;
|
||||
// dk_gray had a 0..65535 component of 12287, and med_gray had a 0..65535 component of 24574
|
||||
static sf::Color lt_gray = {224,224,224},dk_gray = {48,48,48};
|
||||
rectangle rect = frame, ul_rect;
|
||||
@@ -340,6 +403,122 @@ void cControl::drawFrame(short amt, eFrameStyle frameStyle){
|
||||
}
|
||||
}
|
||||
|
||||
std::string cControl::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
std::string tagName, id;
|
||||
who.GetValue(&tagName);
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Node> node;
|
||||
std::set<std::string> foundAttrs;
|
||||
std::multiset<std::string> foundNodes;
|
||||
int width = 0, height = 0;
|
||||
rectangle frame;
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++){
|
||||
std::string attrName = attr->Name();
|
||||
foundAttrs.insert(attrName);
|
||||
if(attrName == "name") attr->GetValue(&id);
|
||||
else if(attrName == "top") attr->GetValue(&frame.top);
|
||||
else if(attrName == "left") attr->GetValue(&frame.left);
|
||||
else if(attrName == "width") attr->GetValue(&width);
|
||||
else if(attrName == "height") attr->GetValue(&height);
|
||||
else if(!parseAttribute(*attr, tagName, fname))
|
||||
throw xBadAttr(tagName, attrName, attr->Row(), attr->Column(), fname);
|
||||
}
|
||||
std::string text;
|
||||
for(node = node.begin(&who); node != node.end(); node++){
|
||||
int type = node->Type();
|
||||
std::string nodeTag;
|
||||
if(type == TiXmlNode::ELEMENT)
|
||||
nodeTag = node->Value();
|
||||
if(type == TiXmlNode::COMMENT) continue;
|
||||
else if(!parseContent(*node, foundNodes.count(nodeTag), tagName, fname, text)) {
|
||||
std::string val = nodeTag.empty() ? nodeTag : xBadVal::CONTENT;
|
||||
throw xBadVal(tagName, xBadVal::CONTENT, val, node->Row(), node->Column(), fname);
|
||||
}
|
||||
foundNodes.insert(nodeTag);
|
||||
}
|
||||
setText(text);
|
||||
location bestSz = getPreferredSize();
|
||||
frame.width() = width > 0 ? width : bestSz.x;
|
||||
frame.height() = height > 0 ? height : bestSz.y;
|
||||
setBounds(frame);
|
||||
validatePostParse(who, fname, foundAttrs, foundNodes);
|
||||
return id;
|
||||
}
|
||||
|
||||
bool cControl::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
std::string name;
|
||||
attr.GetName(&name);
|
||||
// Colour and formatting, if supported
|
||||
if(name == "framed" && canFormat(TXT_FRAME)) {
|
||||
std::string val;
|
||||
attr.GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_FRAME, FRM_SOLID);
|
||||
else if(val == "false") setFormat(TXT_FRAME, FRM_NONE);
|
||||
else throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
if(name == "outline" && canFormat(TXT_FRAME)) {
|
||||
std::string val;
|
||||
attr.GetValue(&val);
|
||||
if(val == "none") setFormat(TXT_FRAME, FRM_NONE);
|
||||
else if(val == "solid") setFormat(TXT_FRAME, FRM_SOLID);
|
||||
else if(val == "inset") setFormat(TXT_FRAME, FRM_INSET);
|
||||
else if(val == "outset") setFormat(TXT_FRAME, FRM_OUTSET);
|
||||
else if(val == "double") setFormat(TXT_FRAME, FRM_DOUBLE);
|
||||
else throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
if(name == "font" && canFormat(TXT_FONT)) {
|
||||
std::string val;
|
||||
attr.GetValue(&val);
|
||||
if(val == "plain") setFormat(TXT_FONT, FONT_PLAIN);
|
||||
else if(val == "bold") setFormat(TXT_FONT, FONT_BOLD);
|
||||
else if(val == "dungeon") setFormat(TXT_FONT, FONT_DUNGEON);
|
||||
else if(val == "maidenword") setFormat(TXT_FONT, FONT_MAIDWORD);
|
||||
else throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
if(name == "size" && canFormat(TXT_SIZE)) {
|
||||
std::string val;
|
||||
attr.GetValue(&val);
|
||||
if(val == "small") setFormat(TXT_SIZE, 10);
|
||||
else if(val == "large") setFormat(TXT_SIZE, 12);
|
||||
else if(val == "title") setFormat(TXT_SIZE, 18);
|
||||
else throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
if(name == "wrap" && canFormat(TXT_WRAP)) {
|
||||
std::string val;
|
||||
attr.GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_WRAP, true);
|
||||
else if(val == "false") setFormat(TXT_WRAP, false);
|
||||
else throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
if((name == "color" || name == "colour") && canFormat(TXT_COLOUR)) {
|
||||
std::string val;
|
||||
try{
|
||||
sf::Color clr = parseColor(val);
|
||||
setColour(clr);
|
||||
} catch(int) {
|
||||
throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool cControl::parseContent(ticpp::Node&, int, std::string, std::string, std::string&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void cControl::validatePostParse(ticpp::Element& elem, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>&) {
|
||||
if(!attrs.count("left")) throw xMissingAttr(elem.Value(), "left", elem.Row(), elem.Column(), fname);
|
||||
if(!attrs.count("top")) throw xMissingAttr(elem.Value(), "top", elem.Row(), elem.Column(), fname);
|
||||
}
|
||||
|
||||
cControl::~cControl() {}
|
||||
|
||||
eControlType cControl::getType(){
|
||||
|
||||
@@ -25,15 +25,16 @@
|
||||
|
||||
/// Formatting properties
|
||||
enum eFormat {
|
||||
TXT_FRAME, ///< Whether to draw a frame around the control. Should be a boolean (true or false).
|
||||
TXT_FRAME, ///< The control's frame style. Should be an enum from @ref eFrameStyle.
|
||||
TXT_FONT, ///< The control's text font. Should be one of the constants FONT_PLAIN, FONT_BOLD, FONT_DUNGEON, FONT_MAIDEN.
|
||||
TXT_SIZE, ///< The control's text size. Should be an integer indicating point size.
|
||||
TXT_WRAP, ///< Whether the control should wrap. Should be a boolean (true or false).
|
||||
TXT_FRAMESTYLE, ///< The control's frame style. Should be an enum from @ref eFrameStyle.
|
||||
TXT_COLOUR, ///< The control's text colour. Should be an sf::Color. Use the separate set/getColour functions to set this.
|
||||
};
|
||||
|
||||
/// Frame styles
|
||||
enum eFrameStyle {
|
||||
FRM_NONE, ///< No frame.
|
||||
FRM_INSET, ///< An outline style that makes it look like the interior is slightly depressed.
|
||||
FRM_OUTSET, ///< An outline style that makes it look like the interior is slightly raise.
|
||||
FRM_SOLID, ///< A solid outline.
|
||||
@@ -91,8 +92,46 @@ public:
|
||||
class cControl {
|
||||
public:
|
||||
using storage_t = std::map<std::string, boost::any>;
|
||||
protected:
|
||||
/// Parses the control from an XML element
|
||||
virtual std::string parse(ticpp::Element& who, std::string fname) = 0;
|
||||
/// Most controls probably don't need to override this. Override parseAttribute() and parseContent() instead.
|
||||
/// @param who A reference to the XML element being parsed.
|
||||
/// @param fname The file being parsed, for error messages.
|
||||
/// @return The unique ID of the widget.
|
||||
/// @throw xBadNode if an unsupported sub-element is detected, or if text is found in an element that does not support it
|
||||
virtual std::string parse(ticpp::Element& who, std::string fname);
|
||||
/// Parses an attribute on the XML element representing this control.
|
||||
/// All controls should defer to cControl::parseAttribute if they don't recognize the attribute.
|
||||
/// @param attr A reference to the XML attribute being parsed.
|
||||
/// @param tagName The name of the XML element, for error messages.
|
||||
/// @param fname The file being parsed, for error messages.
|
||||
/// @return true if the attribute is valid and was successfully parsed, false if it is unrecognized.
|
||||
/// @throw xBadVal if the attribute is allowed but its content is invalid.
|
||||
virtual bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname);
|
||||
/// Parses content of the XML element representing this control, either text or a nested element.
|
||||
/// Comments will not be passed to this function.
|
||||
/// @param content A reference to the XML node being parsed; it will be either an element node or a text node.
|
||||
/// @param tagName The name of the XML parent element, for error messages.
|
||||
/// @param counter The number of previously-parsed nodes of the same tag name (or previously-parsed text nodes), excluding the current one.
|
||||
/// @param[out] text If non-empty, this becomes the widget's text content.
|
||||
/// @return true if the node is recognized and allowed in this location, false otherwise.
|
||||
/// @throw xBadAttr if the node is an element and one of its attributes is not allowed.
|
||||
/// @throw xMissingAttr if the node is an element and is missing a required attribute.
|
||||
/// @throw xMissingElem if the node is an element and is missing a mandatory sub-element.
|
||||
/// @throw xBadVal if the value of the node or (if the node is an element) an attribute is invalid.
|
||||
/// The third argument can be used to accumulate the control's text.
|
||||
virtual bool parseContent(ticpp::Node& content, int counter, std::string tagName, std::string fname, std::string& text);
|
||||
/// Performs final validation of a parsed widget.
|
||||
/// This can be used to throw errors for missing required attributes or elements,
|
||||
/// or set defaults for optional values that were not found while parsing.
|
||||
/// @param who A reference to the XML element being validated.
|
||||
/// @param fname The file being parsed, for error messages
|
||||
/// @param attrs A set containing all the attributes parsed from the widget's root element.
|
||||
/// @param nodes A multiset containing all the sub-elements parsed from the widget's root element. Text nodes are also included in this set under the key "".
|
||||
/// @throw xMissingAttr if a required attribute is missing
|
||||
/// @throw xMissingElem if a required attribute is either missing or present in insufficient quantity
|
||||
virtual void validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes);
|
||||
public:
|
||||
/// 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);
|
||||
@@ -203,6 +242,11 @@ public:
|
||||
/// Set the bounding rect of this control.
|
||||
/// @param newBounds The new bounding rect.
|
||||
void setBounds(rectangle newBounds);
|
||||
/// Calculate a preferred size for this control.
|
||||
/// This can specify an exact preferred size or just a preferred width or height.
|
||||
/// The preferred size is only used if the size is not specified in the XML.
|
||||
/// @return The preferred size, or (0,0) if there is no preferred size.
|
||||
virtual location getPreferredSize() {return {0,0};}
|
||||
/// Set the position of this control.
|
||||
/// @param to The new position.
|
||||
void relocate(location to);
|
||||
@@ -216,20 +260,27 @@ public:
|
||||
/// @param prop The parameter to set.
|
||||
/// @param val The desired value of the parameter.
|
||||
/// @throw xUnsupportedProp if this control doesn't support the given parameter.
|
||||
virtual void setFormat(eFormat prop, short val) = 0;
|
||||
void setFormat(eFormat prop, short val);
|
||||
/// Get one of the control's formatting parameters.
|
||||
/// @param prop The parameter to retrieve.
|
||||
/// @return The value of the parameter.
|
||||
/// @throw xUnsupportedProp if this control doesn't support the given parameter.
|
||||
virtual short getFormat(eFormat prop) = 0;
|
||||
short getFormat(eFormat prop);
|
||||
/// Test if the control supports a given formatting parameter
|
||||
/// @param prop The parameter to check.
|
||||
/// @return true if supported, false if not.
|
||||
bool canFormat(eFormat prop);
|
||||
/// Set the control's colour (usually text colour).
|
||||
/// @param clr The desired colour.
|
||||
/// @throw xUnsupportedProp if this control does not support colour.
|
||||
virtual void setColour(sf::Color clr) = 0;
|
||||
void setColour(sf::Color clr);
|
||||
/// Get the control's colour.
|
||||
/// @return The current colour.
|
||||
/// @throw xUnsupportedProp if this control does not support colour.
|
||||
virtual sf::Color getColour() = 0;
|
||||
sf::Color getColour();
|
||||
/// Test if the control supports colour
|
||||
/// @return true if supported, false if not.
|
||||
bool canColour();
|
||||
/// Check if the control is clickable.
|
||||
/// @return true if it's clickable.
|
||||
/// @note This does not indicate whether the control supports click handlers.
|
||||
@@ -326,6 +377,14 @@ protected:
|
||||
if(handler) return handler(dlg, id, newVal);
|
||||
return true;
|
||||
}
|
||||
/// Called to manage a format setting on this control.
|
||||
/// No action is taken if the parameter is unsupported.
|
||||
/// @param prop The parameter to manage.
|
||||
/// @param set Whether to set the value.
|
||||
/// @param val If @a set is true, set to this value, otherwise store the value here. Ignored if null.
|
||||
/// The real type of this value depends on @a prop.
|
||||
/// @return true if the parameter is supported, false otherwise.
|
||||
virtual bool manageFormat(eFormat prop, bool set, boost::any* val);
|
||||
/// Parses an HTML colour code.
|
||||
/// Recognizes three-digit hex, six-digit hex, and HTML colour names.
|
||||
/// @param code The colour code to parse.
|
||||
|
||||
@@ -165,20 +165,17 @@ bool cTextField::handleClick(location clickLoc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void cTextField::setFormat(eFormat prop, short){
|
||||
throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cTextField::getFormat(eFormat prop){
|
||||
throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
void cTextField::setColour(sf::Color clr) {
|
||||
color = clr;
|
||||
}
|
||||
|
||||
sf::Color cTextField::getColour() {
|
||||
return color;
|
||||
bool cTextField::manageFormat(eFormat prop, bool set, boost::any* val) {
|
||||
switch(prop) {
|
||||
case TXT_COLOUR:
|
||||
if(val) {
|
||||
if(set) color = boost::any_cast<sf::Color>(*val);
|
||||
else *val = color;
|
||||
}
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
eFldType cTextField::getInputType() {
|
||||
@@ -638,61 +635,33 @@ 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);
|
||||
bool cTextField::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
std::string name = attr.Name();
|
||||
if(name == "type"){
|
||||
std::string val = attr.Value();
|
||||
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(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
} else if(name == "tab-order"){
|
||||
attr.GetValue(&tabOrder);
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
return cControl::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
bool cTextField::parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) {
|
||||
if(content.Type() == TiXmlNode::TEXT) {
|
||||
text += dlogStringFilter(content.Value());
|
||||
return true;
|
||||
}
|
||||
setText(content);
|
||||
return id;
|
||||
return cControl::parseContent(content, n, tagName, fname, text);
|
||||
}
|
||||
|
||||
aTextInsert::aTextInsert(cTextField& in, int at, std::string text) : cAction("insert text"), in(in), at(at), text(text) {}
|
||||
|
||||
@@ -33,7 +33,8 @@ enum eFldType {
|
||||
/// There is no Unicode support.
|
||||
class cTextField : public cControl {
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname) override;
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
|
||||
/// For text fields, this is triggered when it loses or gains the input focus.
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
@@ -42,9 +43,6 @@ public:
|
||||
return {EVT_FOCUS, EVT_DEFOCUS};
|
||||
}
|
||||
bool handleClick(location where) override;
|
||||
void setFormat(eFormat prop, short val) override;
|
||||
short getFormat(eFormat prop) override;
|
||||
void setColour(sf::Color clr) override;
|
||||
void setText(std::string to) override;
|
||||
storage_t store() override;
|
||||
void restore(storage_t to) override;
|
||||
@@ -54,7 +52,6 @@ public:
|
||||
/// Set the input type of the field.
|
||||
/// @param newType The new input type.
|
||||
void setInputType(eFldType newType);
|
||||
sf::Color getColour() override;
|
||||
/// Create a new editable text field.
|
||||
/// @param parent The parent dialog.
|
||||
explicit cTextField(cDialog& parent);
|
||||
@@ -76,6 +73,7 @@ public:
|
||||
private:
|
||||
void callHandler(event_fcn<EVT_FOCUS>::type onFocus, cDialog& me, std::string id) override;
|
||||
bool callHandler(event_fcn<EVT_DEFOCUS>::type onFocus, cDialog& me, std::string id) override;
|
||||
bool manageFormat(eFormat prop, bool set, boost::any* val) override;
|
||||
void set_ip(location clickLoc, int cTextField::* insertionPoint);
|
||||
cUndoList history;
|
||||
action_ptr current_action;
|
||||
|
||||
@@ -12,167 +12,85 @@
|
||||
|
||||
extern sf::Texture bg_gworld;
|
||||
|
||||
void cTextMsg::setColour(sf::Color clr) {
|
||||
color = clr;
|
||||
}
|
||||
|
||||
void cTextMsg::setFormat(eFormat prop, short val){
|
||||
switch(prop){
|
||||
bool cTextMsg::manageFormat(eFormat prop, bool set, boost::any* val) {
|
||||
switch(prop) {
|
||||
case TXT_FRAME:
|
||||
drawFramed = val;
|
||||
break;
|
||||
case TXT_FRAMESTYLE:
|
||||
frameStyle = eFrameStyle(val);
|
||||
if(val) {
|
||||
if(set) frameStyle = boost::any_cast<eFrameStyle>(*val);
|
||||
else *val = frameStyle;
|
||||
}
|
||||
break;
|
||||
case TXT_SIZE:
|
||||
textSize = val;
|
||||
if(val) {
|
||||
if(set) textSize = boost::any_cast<short>(*val);
|
||||
else *val = textSize;
|
||||
}
|
||||
break;
|
||||
case TXT_FONT:
|
||||
if(val == FONT_DUNGEON) textFont = FONT_DUNGEON;
|
||||
else if(val == FONT_PLAIN) textFont = FONT_PLAIN;
|
||||
else if(val == FONT_MAIDWORD) textFont = FONT_MAIDWORD;
|
||||
else textFont = FONT_BOLD; // Defaults to bold if an invalid value is provided.
|
||||
if(val) {
|
||||
if(set) textFont = boost::any_cast<eFont>(*val);
|
||||
else *val = textFont;
|
||||
}
|
||||
break;
|
||||
case TXT_WRAP:
|
||||
throw xUnsupportedProp(prop);
|
||||
}
|
||||
}
|
||||
|
||||
sf::Color cTextMsg::getColour() {
|
||||
return color;
|
||||
}
|
||||
|
||||
short cTextMsg::getFormat(eFormat prop){
|
||||
switch(prop){
|
||||
case TXT_FRAME:
|
||||
return drawFramed;
|
||||
case TXT_FRAMESTYLE:
|
||||
return frameStyle;
|
||||
case TXT_SIZE:
|
||||
return textSize;
|
||||
case TXT_FONT:
|
||||
return textFont;
|
||||
case TXT_WRAP:
|
||||
throw xUnsupportedProp(prop);
|
||||
}
|
||||
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 == "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 == "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);
|
||||
case TXT_COLOUR:
|
||||
if(val) {
|
||||
if(set) color = boost::any_cast<sf::Color>(*val);
|
||||
else *val = color;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cTextMsg::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
if(attr.Name() == "def-key"){
|
||||
std::string val = attr.Value();
|
||||
try {
|
||||
attachKey(parseKey(val));
|
||||
} catch(int){
|
||||
throw xBadVal(tagName, attr.Name(), val, attr.Row(), attr.Column(), fname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
setText(content);
|
||||
return id;
|
||||
return cControl::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
bool cTextMsg::parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) {
|
||||
if(content.Type() == TiXmlNode::TEXT) {
|
||||
text += dlogStringFilter(content.Value());
|
||||
return true;
|
||||
} else if(content.Value() == "br") {
|
||||
// TODO: De-magic the | character
|
||||
text += '|'; // because vertical bar is replaced by a newline when drawing strings
|
||||
return true;
|
||||
}
|
||||
return cControl::parseContent(content, n, tagName, fname, text);
|
||||
}
|
||||
|
||||
void cTextMsg::validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) {
|
||||
cControl::validatePostParse(who, fname, attrs, nodes);
|
||||
if(!attrs.count("color") && !attrs.count("colour") && parent->getBg() == cDialog::BG_DARK)
|
||||
setColour(sf::Color::White);
|
||||
}
|
||||
|
||||
cTextMsg::cTextMsg(cDialog& parent) :
|
||||
cControl(CTRL_TEXT,parent),
|
||||
drawFramed(false),
|
||||
textFont(FONT_BOLD),
|
||||
textSize(10),
|
||||
color(parent.getDefTextClr()),
|
||||
fromList("none") {}
|
||||
fromList("none") {
|
||||
setFormat(TXT_FRAME, FRM_NONE);
|
||||
}
|
||||
|
||||
cTextMsg::cTextMsg(sf::RenderWindow& parent) :
|
||||
cControl(CTRL_TEXT,parent),
|
||||
drawFramed(false),
|
||||
textFont(FONT_BOLD),
|
||||
textSize(10),
|
||||
color(cDialog::defaultBackground == cDialog::BG_DARK ? sf::Color::White : sf::Color::Black),
|
||||
fromList("none") {}
|
||||
fromList("none") {
|
||||
setFormat(TXT_FRAME, FRM_NONE);
|
||||
}
|
||||
|
||||
bool cTextMsg::isClickable(){
|
||||
return haveHandler(EVT_CLICK);
|
||||
@@ -195,7 +113,7 @@ void cTextMsg::draw(){
|
||||
TextStyle style;
|
||||
style.font = textFont;
|
||||
style.pointSize = textSize;
|
||||
if(drawFramed) drawFrame(2,frameStyle);
|
||||
drawFrame(2, frameStyle);
|
||||
sf::Color draw_color = color;
|
||||
if(depressed){
|
||||
draw_color.r = 256 - draw_color.r;
|
||||
|
||||
@@ -22,11 +22,10 @@
|
||||
/// 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 setFormat(eFormat prop, short val);
|
||||
short getFormat(eFormat prop);
|
||||
void setColour(sf::Color clr);
|
||||
sf::Color getColour();
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
|
||||
void validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) override;
|
||||
bool manageFormat(eFormat prop, bool set, boost::any* val);
|
||||
/// Create a new text message.
|
||||
/// @param parent The parent dialog.
|
||||
explicit cTextMsg(cDialog& parent);
|
||||
@@ -47,7 +46,6 @@ public:
|
||||
cTextMsg& operator=(cTextMsg& other) = delete;
|
||||
cTextMsg(cTextMsg& other) = delete;
|
||||
private:
|
||||
bool drawFramed;
|
||||
short textSize;
|
||||
eFont textFont;
|
||||
sf::Color color;
|
||||
|
||||
@@ -75,27 +75,24 @@ std::map<ePicType,void(cPict::*)(short,rectangle)>& cPict::drawPict(){
|
||||
return f;
|
||||
}
|
||||
|
||||
void cPict::setFormat(eFormat prop, short val){
|
||||
if(prop == TXT_FRAME) drawFramed = val;
|
||||
else if(prop == TXT_FRAMESTYLE) frameStyle = eFrameStyle(val);
|
||||
else if(prop == TXT_WRAP) drawScaled = !val;
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cPict::getFormat(eFormat prop){
|
||||
if(prop == TXT_FRAME) return drawFramed;
|
||||
else if(prop == TXT_FRAMESTYLE) return frameStyle;
|
||||
else if(prop == TXT_WRAP) return !drawScaled;
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
void cPict::setColour(sf::Color) {
|
||||
// TODO: Colour is not supported
|
||||
}
|
||||
|
||||
sf::Color cPict::getColour() {
|
||||
// TODO: Colour is not supported
|
||||
return sf::Color();
|
||||
bool cPict::manageFormat(eFormat prop, bool set, boost::any* val) {
|
||||
switch(prop) {
|
||||
case TXT_FRAME:
|
||||
if(val) {
|
||||
if(set) frameStyle = boost::any_cast<eFrameStyle>(*val);
|
||||
else *val = frameStyle;
|
||||
}
|
||||
break;
|
||||
case TXT_WRAP:
|
||||
if(val) {
|
||||
if(set) drawScaled = !boost::any_cast<bool>(*val);
|
||||
else *val = !drawScaled;
|
||||
}
|
||||
break;
|
||||
// TODO: Color is not supported
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPict::setPict(pic_num_t num, ePicType type){
|
||||
@@ -133,12 +130,14 @@ ePicType cPict::getPicType(){
|
||||
}
|
||||
|
||||
cPict::cPict(cDialog& parent) :
|
||||
cControl(CTRL_PICT,parent),
|
||||
drawFramed(true) {}
|
||||
cControl(CTRL_PICT,parent) {
|
||||
setFormat(TXT_FRAME, FRM_SOLID);
|
||||
}
|
||||
|
||||
cPict::cPict(sf::RenderWindow& parent) :
|
||||
cControl(CTRL_PICT, parent),
|
||||
drawFramed(true) {}
|
||||
cControl(CTRL_PICT, parent) {
|
||||
setFormat(TXT_FRAME, FRM_SOLID);
|
||||
}
|
||||
|
||||
bool cPict::isClickable(){
|
||||
return haveHandler(EVT_CLICK);
|
||||
@@ -435,141 +434,95 @@ 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);
|
||||
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 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("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);
|
||||
|
||||
bool cPict::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
std::string name = attr.Name();
|
||||
if(name == "type") {
|
||||
std::string val = attr.Value();
|
||||
if(val == "blank")
|
||||
blank = true;
|
||||
else if(val == "ter")
|
||||
picType = PIC_TER;
|
||||
else if(val == "teranim")
|
||||
picType = PIC_TER_ANIM;
|
||||
else if(val == "monst")
|
||||
picType = PIC_MONST;
|
||||
else if(val == "dlog")
|
||||
picType = PIC_DLOG;
|
||||
else if(val == "talk")
|
||||
picType = PIC_TALK;
|
||||
else if(val == "scen")
|
||||
picType = PIC_SCEN;
|
||||
else if(val == "item")
|
||||
picType = PIC_ITEM;
|
||||
else if(val == "pc")
|
||||
picType = PIC_PC;
|
||||
else if(val == "field")
|
||||
picType = PIC_FIELD;
|
||||
else if(val == "boom")
|
||||
picType = PIC_BOOM;
|
||||
else if(val == "missile")
|
||||
picType = PIC_MISSILE;
|
||||
else if(val == "full")
|
||||
picType = PIC_FULL;
|
||||
else if(val == "map")
|
||||
picType = PIC_TER_MAP;
|
||||
else if(val == "status")
|
||||
picType = PIC_STATUS;
|
||||
else throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
} else if(name == "num") {
|
||||
try {
|
||||
attr.GetValue(&picNum);
|
||||
} catch(ticpp::Exception&) {
|
||||
throw xBadVal(tagName, name, attr.Value(), attr.Row(), attr.Column(), fname);
|
||||
}
|
||||
} else if(tiny && type == PIC_ITEM) {
|
||||
pic_num_t wasPic = getPicNum();
|
||||
setPict(wasPic, PIC_TINY_ITEM);
|
||||
return true;
|
||||
} else if(name == "custom") {
|
||||
custom = true;
|
||||
return true;
|
||||
} else if(name == "size") {
|
||||
std::string val = attr.Value();
|
||||
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(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
} else if(name == "scaled") {
|
||||
std::string val = attr.Value();
|
||||
if(val == "true") setFormat(TXT_WRAP, false);
|
||||
else if(val == "false") setFormat(TXT_WRAP, true);
|
||||
else throw xBadVal(tagName, name, val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
} else if(name == "def-key") {
|
||||
try {
|
||||
attachKey(parseKey(attr.Value()));
|
||||
} catch(int) {
|
||||
throw xBadVal(tagName, name, attr.Value(), attr.Row(), attr.Column(), fname);
|
||||
}
|
||||
return true;
|
||||
} else if(name == "wrap") {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
return cControl::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
void cPict::validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) {
|
||||
if(!attrs.count("type")) throw xMissingAttr(who.Value(), "type", who.Row(), who.Column(), fname);
|
||||
if(blank && attrs.count("num")) throw xBadAttr(who.Value(), "num", who.Row(), who.Column(), fname);
|
||||
else if(!blank && !attrs.count("num")) throw xMissingAttr(who.Value(), "num", who.Row(), who.Column(), fname);
|
||||
|
||||
if(blank) picType = PIC_MONST, picNum = BLANK;
|
||||
else if(tiny && picType == PIC_ITEM) picType = PIC_TINY_ITEM;
|
||||
else if(custom) picType += PIC_CUSTOM;
|
||||
|
||||
if(wide && tall) picType += PIC_LARGE;
|
||||
else if(wide) picType += PIC_WIDE;
|
||||
else if(tall) picType += PIC_TALL;
|
||||
|
||||
setPict(picNum, picType);
|
||||
return cControl::validatePostParse(who, fname, attrs, nodes);
|
||||
}
|
||||
|
||||
void cPict::recalcRect() {
|
||||
@@ -733,7 +686,7 @@ void cPict::draw(){
|
||||
fill_rect(*inWindow, rect, sf::Color::Black);
|
||||
else (this->*drawPict()[picType])(picNum,rect);
|
||||
|
||||
if(drawFramed) drawFrame(2,frameStyle);
|
||||
drawFrame(2, frameStyle);
|
||||
}
|
||||
|
||||
void cPict::drawPresetTer(short num, rectangle to_rect){
|
||||
@@ -1325,7 +1278,7 @@ void cPict::drawAt(sf::RenderWindow& win, rectangle dest, pic_num_t which_g, ePi
|
||||
cPict pic(win);
|
||||
pic.frame = dest;
|
||||
pic.setPict(which_g, type_g);
|
||||
pic.setFormat(TXT_FRAME, framed);
|
||||
pic.setFormat(TXT_FRAME, framed ? FRM_SOLID : FRM_NONE);
|
||||
pic.draw();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,9 @@ class cPict : public cControl {
|
||||
public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void setFormat(eFormat prop, short val);
|
||||
short getFormat(eFormat prop);
|
||||
void setColour(sf::Color clr);
|
||||
sf::Color getColour();
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
void validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) override;
|
||||
bool manageFormat(eFormat prop, bool set, boost::any* val);
|
||||
storage_t store();
|
||||
void restore(storage_t to);
|
||||
/// @copydoc setPict(pic_num_t)
|
||||
@@ -93,7 +91,9 @@ private:
|
||||
static short animFrame;
|
||||
pic_num_t picNum;
|
||||
ePicType picType;
|
||||
bool drawFramed, drawScaled;
|
||||
bool drawScaled;
|
||||
// Transient parse flags
|
||||
bool wide = false, tall = false, tiny = false, custom = false, blank = false;
|
||||
void drawPresetTer(short num, rectangle to_rect);
|
||||
void drawPresetTerAnim(short num, rectangle to_rect);
|
||||
void drawPresetMonstSm(short num, rectangle to_rect);
|
||||
|
||||
@@ -519,54 +519,46 @@ void cScrollbar::draw() {
|
||||
else draw_horizontal();
|
||||
}
|
||||
|
||||
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);
|
||||
bool cScrollbar::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
std::string name = attr.Name();
|
||||
if(name == "vertical"){
|
||||
std::string val;
|
||||
attr.GetValue(&val);
|
||||
if(val == "true") vert = true;
|
||||
else vert = false;
|
||||
}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);
|
||||
}else if(name == "page-size"){
|
||||
attr.GetValue(&pgsz);
|
||||
}
|
||||
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);
|
||||
return cControl::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
|
||||
void cScrollbar::validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) {
|
||||
cControl::validatePostParse(who, fname, attrs, nodes);
|
||||
if(!attrs.count("max")) throw xMissingAttr(who.Value(), "max", who.Row(), who.Column(), fname);
|
||||
if(pos > max) throw xBadVal(who.Value(), "initial", std::to_string(pos), who.Row(), who.Column(), fname);
|
||||
if(!attrs.count("vertical")) {
|
||||
// Try to guess whether it's horizontal or vertical based on its size
|
||||
int width, height;
|
||||
who.GetAttributeOrDefault("width", &width, 0);
|
||||
who.GetAttributeOrDefault("height", &height, 0);
|
||||
if(height > width) vert = true;
|
||||
else if(width > height) vert = false;
|
||||
else throw xMissingAttr(who.Value(), "vertical", 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;
|
||||
@@ -585,10 +577,14 @@ std::string cScrollbar::parse(ticpp::Element& who, std::string fname) {
|
||||
if(vert) frame.height() = 25;
|
||||
else frame.height() = thickness;
|
||||
}
|
||||
setBounds(frame);
|
||||
*/
|
||||
if(parent->hasControl(link))
|
||||
parent->getControl(link).setTextToNum(pos);
|
||||
return id;
|
||||
}
|
||||
|
||||
location cScrollbar::getPreferredSize() {
|
||||
if(vert) return {up_rect[style][VERT].width(), 0};
|
||||
else return {0, up_rect[style][HORZ].height()};
|
||||
}
|
||||
|
||||
cControl::storage_t cScrollbar::store() {
|
||||
|
||||
@@ -64,7 +64,9 @@ class cScrollbar : public cControl, public iEventListener, public iDrawable {
|
||||
public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
void validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) override;
|
||||
location getPreferredSize() override;
|
||||
/// Create a new scrollbar without a parent dialog.
|
||||
/// @param parent The parent window.
|
||||
explicit cScrollbar(sf::RenderWindow& parent);
|
||||
|
||||
@@ -70,25 +70,18 @@ void cScrollPane::recalcRect() {
|
||||
frame.right += scrollFrame.width();
|
||||
}
|
||||
|
||||
void cScrollPane::setFormat(eFormat prop, short val) {
|
||||
if(prop == TXT_FRAME) framed = val;
|
||||
else if(prop == TXT_FRAMESTYLE) frameStyle = eFrameStyle(val);
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cScrollPane::getFormat(eFormat prop) {
|
||||
if(prop == TXT_FRAME) return framed;
|
||||
else if(prop == TXT_FRAMESTYLE) return frameStyle;
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
void cScrollPane::setColour(sf::Color) {
|
||||
// TODO: Colour is not supported
|
||||
}
|
||||
|
||||
sf::Color cScrollPane::getColour() {
|
||||
// TODO: Colour is not supported
|
||||
return sf::Color();
|
||||
bool cScrollPane::manageFormat(eFormat prop, bool set, boost::any* val) {
|
||||
switch(prop) {
|
||||
case TXT_FRAME:
|
||||
if(val) {
|
||||
if(set) frameStyle = boost::any_cast<eFrameStyle>(*val);
|
||||
else *val = frameStyle;
|
||||
}
|
||||
break;
|
||||
// TODO: Colour is not supported
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
cControl::storage_t cScrollPane::store() {
|
||||
@@ -179,92 +172,52 @@ void cScrollPane::forEach(std::function<void(std::string,cControl&)> callback) {
|
||||
callback(ctrl.first, *ctrl.second);
|
||||
}
|
||||
|
||||
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);
|
||||
bool cScrollPane::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
if(attr.Name() == "style"){
|
||||
std::string val = attr.Value();
|
||||
if(val == "white") setStyle(SCROLL_WHITE);
|
||||
else if(val == "led") setStyle(SCROLL_LED);
|
||||
else throw xBadVal(tagName, attr.Name(), val, attr.Row(), attr.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
return cContainer::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
bool cScrollPane::parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) {
|
||||
if(content.Type() == TiXmlNode::ELEMENT) {
|
||||
std::string tag = content.Value();
|
||||
auto& elem = dynamic_cast<ticpp::Element&>(content);
|
||||
if(tag == "field") {
|
||||
auto field = parent->parse<cTextField>(elem);
|
||||
contents.insert(field);
|
||||
// TODO: Add field to tab order
|
||||
//tabOrder.push_back(field);
|
||||
} else if(tag == "text") {
|
||||
auto text = parent->parse<cTextMsg>(elem);
|
||||
contents.insert(text);
|
||||
} else if(tag == "pict") {
|
||||
auto pict = parent->parse<cPict>(elem);
|
||||
contents.insert(pict);
|
||||
} else if(tag == "slider") {
|
||||
auto slide = parent->parse<cScrollbar>(elem);
|
||||
contents.insert(slide);
|
||||
} else if(tag == "button") {
|
||||
auto button = parent->parse<cButton>(elem);
|
||||
contents.insert(button);
|
||||
} else if(tag == "led") {
|
||||
auto led = parent->parse<cLed>(elem);
|
||||
contents.insert(led);
|
||||
} else if(tag == "group") {
|
||||
auto group = parent->parse<cLedGroup>(elem);
|
||||
contents.insert(group);
|
||||
} else throw xBadNode(tag, content.Row(), content.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
return cContainer::parseContent(content, n, tagName, fname, text);
|
||||
}
|
||||
|
||||
void cScrollPane::validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) {
|
||||
cContainer::validatePostParse(who, fname, attrs, nodes);
|
||||
if(!attrs.count("style")) setStyle(SCROLL_LED);
|
||||
recalcRect();
|
||||
}
|
||||
|
||||
@@ -20,15 +20,14 @@ class cScrollPane : public cContainer {
|
||||
std::map<std::string, cControl*> contents;
|
||||
rectangle globalFrame;
|
||||
bool framed = false;
|
||||
bool manageFormat(eFormat prop, bool set, boost::any* val) override;
|
||||
public:
|
||||
/// Create a new scroll pane
|
||||
explicit cScrollPane(cDialog& parent);
|
||||
std::string parse(ticpp::Element& who, std::string fname) override;
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
|
||||
void validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) override;
|
||||
bool handleClick(location where) override;
|
||||
void setFormat(eFormat prop, short val) override;
|
||||
short getFormat(eFormat prop) override;
|
||||
void setColour(sf::Color clr) override;
|
||||
sf::Color getColour() override;
|
||||
bool hasChild(std::string id) override;
|
||||
cControl& getChild(std::string id) override;
|
||||
storage_t store() override;
|
||||
|
||||
@@ -32,25 +32,18 @@ void cContainer::callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, st
|
||||
getChild(which_clicked).triggerClickHandler(me, which_clicked, mods);
|
||||
}
|
||||
|
||||
void cStack::setFormat(eFormat prop, short val) {
|
||||
if(prop == TXT_FRAME) drawFramed = val;
|
||||
else if(prop == TXT_FRAMESTYLE) frameStyle = eFrameStyle(val);
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cStack::getFormat(eFormat prop) {
|
||||
if(prop == TXT_FRAME) return drawFramed;
|
||||
else if(prop == TXT_FRAMESTYLE) return frameStyle;
|
||||
throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
void cStack::setColour(sf::Color) {
|
||||
// TODO: Colour is not supported
|
||||
}
|
||||
|
||||
sf::Color cStack::getColour() {
|
||||
// TODO: Colour is not supported
|
||||
return sf::Color();
|
||||
bool cStack::manageFormat(eFormat prop, bool set, boost::any* val) {
|
||||
switch(prop) {
|
||||
case TXT_FRAME:
|
||||
if(val) {
|
||||
if(set) frameStyle = boost::any_cast<eFrameStyle>(*val);
|
||||
else *val = frameStyle;
|
||||
}
|
||||
break;
|
||||
// TODO: Colour is not supported
|
||||
default: return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cStack::isClickable() {
|
||||
@@ -158,65 +151,56 @@ void cStack::forEach(std::function<void(std::string,cControl&)> callback) {
|
||||
callback(ctrl.first, *ctrl.second);
|
||||
}
|
||||
|
||||
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 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("stack",name,attr->Row(),attr->Column(),fname);
|
||||
|
||||
bool cStack::parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) {
|
||||
if(attr.Name() == "pages") {
|
||||
try {
|
||||
size_t n;
|
||||
attr.GetValue(&n);
|
||||
setPageCount(n);
|
||||
} catch(ticpp::Exception&) {
|
||||
throw xBadVal(tagName, attr.Name(), attr.Value(), attr.Row(), attr.Column(), fname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
controls.insert(field);
|
||||
// TODO: Add field to tab order
|
||||
//tabOrder.push_back(field);
|
||||
} else if(val == "text") {
|
||||
auto text = parent->parse<cTextMsg>(*node);
|
||||
controls.insert(text);
|
||||
} else if(val == "pict") {
|
||||
auto pict = parent->parse<cPict>(*node);
|
||||
controls.insert(pict);
|
||||
} else if(val == "slider") {
|
||||
auto slide = parent->parse<cScrollbar>(*node);
|
||||
controls.insert(slide);
|
||||
} else if(val == "button") {
|
||||
auto button = parent->parse<cButton>(*node);
|
||||
controls.insert(button);
|
||||
} else if(val == "led") {
|
||||
auto led = parent->parse<cLed>(*node);
|
||||
controls.insert(led);
|
||||
} else if(val == "group") {
|
||||
auto group = parent->parse<cLedGroup>(*node);
|
||||
controls.insert(group);
|
||||
} 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);
|
||||
}
|
||||
recalcRect();
|
||||
return id;
|
||||
return cContainer::parseAttribute(attr, tagName, fname);
|
||||
}
|
||||
|
||||
bool cStack::parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) {
|
||||
if(content.Type() == TiXmlNode::ELEMENT) {
|
||||
std::string tag = content.Value();
|
||||
auto& elem = dynamic_cast<ticpp::Element&>(content);
|
||||
if(tag == "field") {
|
||||
auto field = parent->parse<cTextField>(elem);
|
||||
controls.insert(field);
|
||||
// TODO: Add field to tab order
|
||||
//tabOrder.push_back(field);
|
||||
} else if(tag == "text") {
|
||||
auto text = parent->parse<cTextMsg>(elem);
|
||||
controls.insert(text);
|
||||
} else if(tag == "pict") {
|
||||
auto pict = parent->parse<cPict>(elem);
|
||||
controls.insert(pict);
|
||||
} else if(tag == "slider") {
|
||||
auto slide = parent->parse<cScrollbar>(elem);
|
||||
controls.insert(slide);
|
||||
} else if(tag == "button") {
|
||||
auto button = parent->parse<cButton>(elem);
|
||||
controls.insert(button);
|
||||
} else if(tag == "led") {
|
||||
auto led = parent->parse<cLed>(elem);
|
||||
controls.insert(led);
|
||||
} else if(tag == "group") {
|
||||
auto group = parent->parse<cLedGroup>(elem);
|
||||
controls.insert(group);
|
||||
} else throw xBadNode(tag, content.Row(), content.Column(), fname);
|
||||
return true;
|
||||
}
|
||||
return cContainer::parseContent(content, n, tagName, fname, text);
|
||||
}
|
||||
|
||||
void cStack::validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) {
|
||||
validatePostParse(who, fname, attrs, nodes);
|
||||
recalcRect();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,12 +37,11 @@ class cStack : public cContainer {
|
||||
std::vector<std::map<std::string,storage_t>> storage;
|
||||
std::map<std::string,cControl*> controls;
|
||||
bool drawFramed = false;
|
||||
bool manageFormat(eFormat prop, bool set, boost::any* val) override;
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname) override;
|
||||
void setFormat(eFormat prop, short val) override;
|
||||
short getFormat(eFormat prop) override;
|
||||
void setColour(sf::Color clr) override;
|
||||
sf::Color getColour() override;
|
||||
bool parseAttribute(ticpp::Attribute& attr, std::string tagName, std::string fname) override;
|
||||
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
|
||||
void validatePostParse(ticpp::Element& who, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& nodes) override;
|
||||
bool isClickable() override;
|
||||
bool isFocusable() override;
|
||||
bool isScrollable() override;
|
||||
|
||||
@@ -520,7 +520,7 @@ static void readQuestFromXml(ticpp::Element& data, cQuest& quest) {
|
||||
elem->GetText(&quest.bank1);
|
||||
else if(banks_found == 1)
|
||||
elem->GetText(&quest.bank2);
|
||||
else throw xBadNode(name, elem->Row(), elem->Column(), fname);
|
||||
else throw xBadNode(type, elem->Row(), elem->Column(), fname);
|
||||
banks_found++;
|
||||
} else if(type == "name") {
|
||||
elem->GetText(&quest.name, false);
|
||||
|
||||
@@ -1620,7 +1620,7 @@ static void put_target_status_graphics(cDialog& me, short for_pc) {
|
||||
for(auto next : univ.party[for_pc].status) {
|
||||
std::string id2 = id + "-stat" + std::to_string(slot + 1);
|
||||
cPict& pic = dynamic_cast<cPict&>(me[id2]);
|
||||
pic.setFormat(TXT_FRAME, false);
|
||||
pic.setFormat(TXT_FRAME, FRM_NONE);
|
||||
if(isAlive) {
|
||||
short placedIcon = -1;
|
||||
if(next.first == eStatus::POISON && next.second > 4) placedIcon = 1;
|
||||
|
||||
@@ -1486,7 +1486,7 @@ void draw_map(bool need_refresh) {
|
||||
cPict theGraphic(mini_map);
|
||||
theGraphic.setBounds(dlogpicrect);
|
||||
theGraphic.setPict(21, PIC_DLOG);
|
||||
theGraphic.setFormat(TXT_FRAME, false);
|
||||
theGraphic.setFormat(TXT_FRAME, FRM_NONE);
|
||||
theGraphic.draw();
|
||||
style.colour = sf::Color::White;
|
||||
style.lineHeight = 12;
|
||||
|
||||
Reference in New Issue
Block a user