Better editing for talk node keys #548
@@ -3,8 +3,10 @@
|
|||||||
<dialog defbtn='okay'>
|
<dialog defbtn='okay'>
|
||||||
<!-- OK button -->
|
<!-- OK button -->
|
||||||
<field name='who' top='26' left='186' width='64' height='16'/>
|
<field name='who' top='26' left='186' width='64' height='16'/>
|
||||||
<field name='key1' top='54' left='165' width='52' height='16'/>
|
<field name='key1' top='54' left='165' width='52' height='16' max-chars='4'/>
|
||||||
<field name='key2' top='54' left='285' width='52' height='16'/>
|
<field name='key2' top='54' left='285' width='52' height='16' max-chars='4'/>
|
||||||
|
<text top='6' left='350' width='160' height='48'>The in-game "Buy" button checks for these response keys, in order: purc, sale, heal, iden, trai, ench</text>
|
||||||
|
<text relative='pos-in pos' rel-anchor='prev' top='0' left='0' width='160' height='50'>The "Sell" button checks for sell.</text>
|
||||||
<field name='extra1' top='114' left='344' width='64' height='16'/>
|
<field name='extra1' top='114' left='344' width='64' height='16'/>
|
||||||
<field name='extra2' top='137' left='344' width='64' height='16'/>
|
<field name='extra2' top='137' left='344' width='64' height='16'/>
|
||||||
<field name='extra3' top='160' left='344' width='64' height='16'/>
|
<field name='extra3' top='160' left='344' width='64' height='16'/>
|
||||||
|
|||||||
@@ -150,6 +150,7 @@
|
|||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
<xs:attribute name="tab-order" type="xs:integer"/>
|
<xs:attribute name="tab-order" type="xs:integer"/>
|
||||||
|
<xs:attribute name="max-chars" type="xs:integer"/>
|
||||||
<xs:attributeGroup ref="rect-size"/>
|
<xs:attributeGroup ref="rect-size"/>
|
||||||
<xs:attributeGroup ref="position"/>
|
<xs:attributeGroup ref="position"/>
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
|
|||||||
@@ -442,6 +442,7 @@ void cTextField::handleInput(cKey key, bool record) {
|
|||||||
handleInput(deleteKey);
|
handleInput(deleteKey);
|
||||||
contents = getText();
|
contents = getText();
|
||||||
}
|
}
|
||||||
|
if(maxChars < 0 || contents.size() < maxChars){
|
||||||
if(aTextInsert* ins = dynamic_cast<aTextInsert*>(current_action.get()))
|
if(aTextInsert* ins = dynamic_cast<aTextInsert*>(current_action.get()))
|
||||||
ins->append(key.c);
|
ins->append(key.c);
|
||||||
else {
|
else {
|
||||||
@@ -452,6 +453,7 @@ void cTextField::handleInput(cKey key, bool record) {
|
|||||||
}
|
}
|
||||||
contents.insert(contents.begin() + insertionPoint, char(key.c));
|
contents.insert(contents.begin() + insertionPoint, char(key.c));
|
||||||
selectionPoint = ++insertionPoint;
|
selectionPoint = ++insertionPoint;
|
||||||
|
}
|
||||||
} else switch(key.k) {
|
} else switch(key.k) {
|
||||||
case key_enter: break; // Shouldn't be receiving this anyway
|
case key_enter: break; // Shouldn't be receiving this anyway
|
||||||
case key_left: case key_word_left:
|
case key_left: case key_word_left:
|
||||||
@@ -681,6 +683,9 @@ bool cTextField::parseAttribute(ticpp::Attribute& attr, std::string tagName, std
|
|||||||
} else if(name == "tab-order"){
|
} else if(name == "tab-order"){
|
||||||
attr.GetValue(&tabOrder);
|
attr.GetValue(&tabOrder);
|
||||||
return true;
|
return true;
|
||||||
|
} else if(name == "max-chars"){
|
||||||
|
attr.GetValue(&maxChars);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return cControl::parseAttribute(attr, tagName, fname);
|
return cControl::parseAttribute(attr, tagName, fname);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,6 +90,10 @@ private:
|
|||||||
rectangle text_rect;
|
rectangle text_rect;
|
||||||
std::vector<snippet_t> snippets;
|
std::vector<snippet_t> snippets;
|
||||||
int ip_row, ip_col;
|
int ip_row, ip_col;
|
||||||
|
/// Setting maxChars AFTER the player has a chance to type in the field would be a bad idea.
|
||||||
|
/// So would calling setText() with a string longer than maxChars.
|
||||||
|
/// Really, it should probably only be set in xml, as the attribute "max-chars".
|
||||||
|
int maxChars = -1;
|
||||||
|
|
|||||||
friend class aTextInsert;
|
friend class aTextInsert;
|
||||||
friend class aTextDelete;
|
friend class aTextDelete;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
#include "scen.global.hpp"
|
#include "scen.global.hpp"
|
||||||
#include "scenario/scenario.hpp"
|
#include "scenario/scenario.hpp"
|
||||||
#include "scenario/town.hpp"
|
#include "scenario/town.hpp"
|
||||||
@@ -25,6 +27,9 @@
|
|||||||
#include "fileio/fileio.hpp"
|
#include "fileio/fileio.hpp"
|
||||||
#include "fileio/resmgr/res_dialog.hpp"
|
#include "fileio/resmgr/res_dialog.hpp"
|
||||||
|
|
||||||
|
using boost::algorithm::trim;
|
||||||
|
using boost::algorithm::to_lower;
|
||||||
|
|
||||||
extern short cen_x, cen_y, overall_mode;
|
extern short cen_x, cen_y, overall_mode;
|
||||||
extern bool mouse_button_held,change_made;
|
extern bool mouse_button_held,change_made;
|
||||||
extern short cur_viewing_mode;
|
extern short cur_viewing_mode;
|
||||||
@@ -932,13 +937,35 @@ static bool check_talk_key(cDialog& me, std::string item_hit, bool losing) {
|
|||||||
if(!losing) return true;
|
if(!losing) return true;
|
||||||
std::string key = me[item_hit].getText();
|
std::string key = me[item_hit].getText();
|
||||||
bool passes = true;
|
bool passes = true;
|
||||||
|
|
||||||
|
// An empty string is fine, it just means there's only one key.
|
||||||
|
if(key.empty()){
|
||||||
|
// But there needs to be at least one.
|
||||||
|
if(me["key1"].getText() == me["key2"].getText()){
|
||||||
|
showError("At least one of the words in this node must be filled.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// I'll always have trouble remembering that it should be 'purc'.
|
||||||
|
// So why not make it easy?
|
||||||
|
if(key == "buy"){
|
||||||
|
me[item_hit].setText("purc");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can convert upper-case letters
|
||||||
|
to_lower(key);
|
||||||
|
me[item_hit].setText(key);
|
||||||
if(key.length() != 4) passes = false;
|
if(key.length() != 4) passes = false;
|
||||||
for(size_t i = 0; i < 4; i++) {
|
for(size_t i = 0; i < 4; i++) {
|
||||||
if(i < key.length() && !islower(key[i]))
|
if(i < key.length() && !islower(key[i])){
|
||||||
passes = false;
|
passes = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(!passes) {
|
if(!passes) {
|
||||||
showError("The words this node is the response to must be 4 characters long, and all characters must be lower case letters.", &me);
|
showError("The words this node is the response to must be 4 characters long, and all characters must be letters.", &me);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -1088,8 +1115,10 @@ static bool save_talk_node(cDialog& me, std::stack<node_ref_t>& talk_edit_stack,
|
|||||||
talk_node.personality = me["who"].getTextAsNum();
|
talk_node.personality = me["who"].getTextAsNum();
|
||||||
|
|
||||||
std::string link = me["key1"].getText();
|
std::string link = me["key1"].getText();
|
||||||
|
if(link.empty()) link = " ";
|
||||||
std::copy(link.begin(), link.begin() + 4, talk_node.link1);
|
std::copy(link.begin(), link.begin() + 4, talk_node.link1);
|
||||||
link = me["key2"].getText();
|
link = me["key2"].getText();
|
||||||
|
if(link.empty()) link = " ";
|
||||||
std::copy(link.begin(), link.begin() + 4, talk_node.link2);
|
std::copy(link.begin(), link.begin() + 4, talk_node.link2);
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++) {
|
for(int i = 0; i < 4; i++) {
|
||||||
@@ -1118,9 +1147,12 @@ static void put_talk_node_in_dlog(cDialog& me, std::stack<node_ref_t>& talk_edit
|
|||||||
|
|
||||||
std::string link = "";
|
std::string link = "";
|
||||||
for(int i = 0; i < 4; i++) link += talk_node.link1[i];
|
for(int i = 0; i < 4; i++) link += talk_node.link1[i];
|
||||||
|
// I don't want 4 spaces in the text fields
|
||||||
|
trim(link);
|
||||||
me["key1"].setText(link);
|
me["key1"].setText(link);
|
||||||
link = "";
|
link = "";
|
||||||
for(int i = 0; i < 4; i++) link += talk_node.link2[i];
|
for(int i = 0; i < 4; i++) link += talk_node.link2[i];
|
||||||
|
trim(link);
|
||||||
me["key2"].setText(link);
|
me["key2"].setText(link);
|
||||||
|
|
||||||
int iDescBase = int(talk_node.type) * 7;
|
int iDescBase = int(talk_node.type) * 7;
|
||||||
|
|||||||
Reference in New Issue
Block a user
I wouldn't call it a priority to have a runtime setter for
maxChars, but I don't think it's something that's difficult to do – it could just truncate the current text to the new maximum length. Similarly,setText()could truncate the text to the current maximum length.