Implement <key> tag in DialogXML which substitutes a buttons key shortcut into its label

This commit is contained in:
2020-02-21 22:25:48 -05:00
parent 7b93726383
commit 9f60f7e378
8 changed files with 88 additions and 44 deletions

View File

@@ -4,21 +4,21 @@
<!-- Unexpected button control -->
<pict name='pic' type='dlog' num='12' top='9' left='9'/>
<text size='large' top='6' left='54' width='139' height='18'>Select a Spell:</text>
<button name='caster1' type='regular' def-key='1' top='81' left='10'>1</button>
<button name='caster2' type='regular' def-key='2' top='105' left='10'>2</button>
<button name='caster3' type='regular' def-key='3' top='129' left='10'>3</button>
<button name='caster4' type='regular' def-key='4' top='153' left='10'>4</button>
<button name='caster5' type='regular' def-key='5' top='177' left='10'>5</button>
<button name='caster6' type='regular' def-key='6' top='201' left='10'>6</button>
<button name='caster1' type='regular' def-key='1' top='81' left='10'><key/></button>
<button name='caster2' type='regular' def-key='2' top='105' left='10'><key/></button>
<button name='caster3' type='regular' def-key='3' top='129' left='10'><key/></button>
<button name='caster4' type='regular' def-key='4' top='153' left='10'><key/></button>
<button name='caster5' type='regular' def-key='5' top='177' left='10'><key/></button>
<button name='caster6' type='regular' def-key='6' top='201' left='10'><key/></button>
<!--
TODO: Use the <key/> element here.
-->
<button name='target1' type='small' def-key='shift 1' top='82' left='235'>!</button>
<button name='target2' type='small' def-key='shift 2' top='106' left='235'>@</button>
<button name='target3' type='small' def-key='shift 3' top='130' left='235'>#</button>
<button name='target4' type='small' def-key='shift 4' top='154' left='235'>$</button>
<button name='target5' type='small' def-key='shift 5' top='178' left='235'>%</button>
<button name='target6' type='small' def-key='shift 6' top='202' left='235'>^</button>
<button name='target1' type='small' def-key='shift 1' top='82' left='235'><key/></button>
<button name='target2' type='small' def-key='shift 2' top='106' left='235'><key/></button>
<button name='target3' type='small' def-key='shift 3' top='130' left='235'><key/></button>
<button name='target4' type='small' def-key='shift 4' top='154' left='235'><key/></button>
<button name='target5' type='small' def-key='shift 5' top='178' left='235'><key/></button>
<button name='target6' type='small' def-key='shift 6' top='202' left='235'><key/></button>
<button name='cancel' type='regular' def-key='esc' top='394' left='479'>Cancel</button>
<button name='cast' type='regular' top='394' left='549'>Cast</button>
<text name='pc1' top='84' left='88' width='122' height='16'/>

View File

@@ -3,12 +3,12 @@
<dialog defbtn='done'>
<button name='done' type='done' top='408' left='337'/>
<pict type='dlog' num='2' top='10' left='10'/>
<button name='pc1' type='small' def-key='1' top='354' left='89'>1</button>
<button name='pc2' type='small' def-key='2' top='354' left='174'>2</button>
<button name='pc3' type='small' def-key='3' top='354' left='259'>3</button>
<button name='pc4' type='small' def-key='4' top='397' left='89'>4</button>
<button name='pc5' type='small' def-key='5' top='397' left='174'>5</button>
<button name='pc6' type='small' def-key='6' top='397' left='259'>6</button>
<button name='pc1' type='small' def-key='1' top='354' left='89'><key/></button>
<button name='pc2' type='small' def-key='2' top='354' left='174'><key/></button>
<button name='pc3' type='small' def-key='3' top='354' left='259'><key/></button>
<button name='pc4' type='small' def-key='4' top='397' left='89'><key/></button>
<button name='pc5' type='small' def-key='5' top='397' left='174'><key/></button>
<button name='pc6' type='small' def-key='6' top='397' left='259'><key/></button>
<button name='up' type='up' def-key='up' top='5' left='342'/>
<button name='down' type='down' def-key='down' top='346' left='342'/>
<pict name='pc1-g' type='pc' num='0' top='348' left='123'/>

View File

@@ -3,12 +3,12 @@
<dialog defbtn='cancel'>
<text top='190' left='11' width='184' height='18'>Hit a button or type '1'-'6'.</text>
<pict type='dlog' num='6' top='8' left='8'/>
<button name='pick1' type='regular' def-key='1' top='31' left='69'>1</button>
<button name='pick2' type='regular' def-key='2' top='56' left='69'>2</button>
<button name='pick3' type='regular' def-key='3' top='81' left='69'>3</button>
<button name='pick4' type='regular' def-key='4' top='106' left='69'>4</button>
<button name='pick5' type='regular' def-key='5' top='131' left='69'>5</button>
<button name='pick6' type='regular' def-key='6' top='156' left='69'>6</button>
<button name='pick1' type='regular' def-key='1' top='31' left='69'><key/></button>
<button name='pick2' type='regular' def-key='2' top='56' left='69'><key/></button>
<button name='pick3' type='regular' def-key='3' top='81' left='69'><key/></button>
<button name='pick4' type='regular' def-key='4' top='106' left='69'><key/></button>
<button name='pick5' type='regular' def-key='5' top='131' left='69'><key/></button>
<button name='pick6' type='regular' def-key='6' top='156' left='69'><key/></button>
<text name='pc1' framed='true' top='35' left='138' width='139' height='16'/>
<text name='pc2' framed='true' top='60' left='138' width='139' height='16'/>
<text name='pc3' framed='true' top='85' left='138' width='139' height='16'/>

View File

@@ -5,16 +5,16 @@
<!--
TODO: What about showing the monster's graphic?
-->
<button name='pick1' type='small' def-key='1' top='50' left='50'>1</button>
<button name='pick1' type='small' def-key='1' top='50' left='50'><key/></button>
<text name='slot1' framed='true' top='52' left='83' width='172' height='16'>(spot empty)</text>
<text name='lvl1' framed='true' top='52' left='262' width='31' height='16'/>
<button name='pick2' type='small' def-key='2' top='72' left='50'>2</button>
<button name='pick2' type='small' def-key='2' top='72' left='50'><key/></button>
<text name='slot2' framed='true' top='74' left='83' width='172' height='16'>(spot empty)</text>
<text name='lvl2' framed='true' top='74' left='262' width='31' height='16'/>
<button name='pick3' type='small' def-key='3' top='94' left='50'>3</button>
<button name='pick3' type='small' def-key='3' top='94' left='50'><key/></button>
<text name='slot3' framed='true' top='96' left='83' width='172' height='16'>(spot empty)</text>
<text name='lvl3' framed='true' top='96' left='262' width='31' height='16'/>
<button name='pick4' type='small' def-key='4' top='116' left='50'>4</button>
<button name='pick4' type='small' def-key='4' top='116' left='50'><key/></button>
<text name='slot4' framed='true' top='118' left='83' width='172' height='16'>(spot empty)</text>
<text name='lvl4' framed='true' top='118' left='262' width='31' height='16'/>
<text size='large' top='6' left='50' width='251' height='16'>Select monster to summon:</text>

View File

@@ -84,7 +84,11 @@ void cButton::draw(){
int w = string_length(lbl, style);
to_rect.inset((w - 30) / -2,0);
}
win_draw_string(*inWindow,to_rect,lbl,textMode,style);
std::string label = lbl, keyDesc = getAttachedKeyDescription();
for(size_t key_pos = label.find_first_of('\a'); key_pos < label.size(); key_pos = label.find_first_of('\a')) {
label.replace(key_pos, 1, keyDesc);
}
win_draw_string(*inWindow,to_rect,label,textMode,style);
// frame default button, to provide a visual cue that it's the default
if(key.spec && key.k == key_enter) drawFrame(2,frameStyle);
}
@@ -151,9 +155,7 @@ bool cButton::parseContent(ticpp::Node& content, int n, std::string tagName, std
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;
text += '\a';
return true;
}
return cControl::parseContent(content, n, tagName, fname, text);

View File

@@ -88,7 +88,6 @@ protected:
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];
protected:

View File

@@ -311,18 +311,60 @@ static unsigned char removeShift(unsigned char c){
return afterUnShift[c - ' '];
}
void cControl::setTextToKey() {
if(key.spec); // TODO: Handle this case
else {
unsigned char c = key.c;
if(key.mod - mod_shift != key.mod) c = applyShift(c);
else c = removeShift(c);
lbl.clear();
if(key.mod - mod_ctrl != key.mod) lbl += '^';
else if(key.mod - mod_alt != key.mod) lbl = '*';
lbl += c;
std::string cControl::getAttachedKeyDescription() {
std::string s;
if(key.spec) {
auto mod = key.mod;
std::string keyName;
switch(key.k) {
case key_left: keyName = "left"; break;
case key_right: keyName = "right"; break;
case key_up: keyName = "up"; break;
case key_down: keyName = "down"; break;
case key_esc: keyName = "esc"; break;
case key_enter: keyName = "enter"; break;
case key_tab: keyName = "tab"; break;
case key_help: keyName = "help"; break;
case key_bsp: keyName = "backspace"; break;
case key_del: keyName = "delete"; break;
case key_home: keyName = "home"; break;
case key_end: keyName = "end"; break;
case key_pgup: keyName = "pgup"; break;
case key_pgdn: keyName = "pgdn"; break;
case key_insert: keyName = "insert"; break;
case key_copy: keyName = "c"; mod += mod_ctrl; break;
case key_cut: keyName = "x"; mod += mod_ctrl; break;
case key_paste: keyName = "v"; mod += mod_ctrl; break;
case key_selectall: keyName = "a"; mod += mod_ctrl; break;
case key_undo: keyName = "z"; mod += mod_ctrl; break;
case key_redo: keyName = "y"; mod += mod_ctrl; break;
case key_top: keyName = "home"; mod += mod_ctrl; break;
case key_bottom: keyName = "end"; mod += mod_ctrl; break;
#ifdef __APPLE__
case key_word_left: keyName = "left"; mod += mod_alt; break;
case key_word_right: keyName = "right"; mod += mod_alt; break;
case key_word_bsp: keyName = "backspace"; mod += mod_alt; break;
case key_word_del: keyName = "delete"; mod += mod_alt; break;
#else
case key_word_left: keyName = "left"; mod += mod_ctrl; break;
case key_word_right: keyName = "right"; mod += mod_ctrl; break;
case key_word_bsp: keyName = "backspace"; mod += mod_ctrl; break;
case key_word_del: keyName = "delete"; mod += mod_ctrl; break;
#endif
}
if(isVisible()) draw();
if(mod_contains(mod, mod_ctrl)) s += '^';
if(mod_contains(mod, mod_alt)) s = '#';
if(mod_contains(mod, mod_shift)) s += '$';
} else {
unsigned char c = key.c;
if(mod_contains(key.mod, mod_shift)) c = applyShift(c);
else c = removeShift(c);
if(mod_contains(key.mod, mod_ctrl)) s += '^';
if(mod_contains(key.mod, mod_alt)) s = '#';
if(c == ' ') s += "space";
else s += c;
}
return s;
}
void cControl::attachKey(cKey key){

View File

@@ -137,8 +137,6 @@ public:
void attachKey(cKey key);
/// Detach any currently assigned keyboard shortcut from the control.
void detachKey();
/// Set the control's text to a representation of its assigned keyboard shortcut.
void setTextToKey();
/// Check if the control has an assigned keyboard shortcut.
/// @return true if a keyboard shortcut is assigned.
bool hasKey();
@@ -146,6 +144,9 @@ public:
/// @return the currently-assigned keyboard shortcut.
/// @note You should first check that a shortcut is assigned using hasKey().
cKey getAttachedKey();
/// Retrieve the control's current keyboard shortcut as a human-readable string.
/// @return the currently-assigned keyboard shortcut, or an empty string if none is assigned.
std::string getAttachedKeyDescription();
/// Attach an event handler to this control.
/// @tparam t The type of event to attach.
/// @param handler The event handler function or functor. Its signature depends on the event type.