Refactor the dialog engine's event handling to make it easier to add new events in the future
- Focus event split into focus and defocus - Scroll event added but not yet properly implemented Also: - Remove the useless (and ignored) clickable attributes from the schema - Pave the way for controls other than fields to be able to recieve keyboard focus
This commit is contained in:
@@ -137,7 +137,6 @@
|
||||
<xs:attributeGroup ref="frame"/>
|
||||
<xs:attributeGroup ref="font"/>
|
||||
<xs:attribute ref="def-key"/>
|
||||
<xs:attribute name="clickable" default="false" type="bool"/>
|
||||
<xs:attribute name="fromlist" default="none" type="xs:string"/>
|
||||
<xs:attributeGroup ref="rect-size"/>
|
||||
</xs:complexType>
|
||||
@@ -161,7 +160,6 @@
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
<xs:attribute ref="def-key"/>
|
||||
<xs:attribute name="clickable" default="false" type="bool"/>
|
||||
<xs:attribute name="num" use="required" type="xs:integer"/>
|
||||
<xs:attributeGroup ref="rect-size"/>
|
||||
</xs:complexType>
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<ClInclude Include="..\..\dialogxml\control.hpp" />
|
||||
<ClInclude Include="..\..\dialogxml\dialog.hpp" />
|
||||
<ClInclude Include="..\..\dialogxml\dialog.keys.hpp" />
|
||||
<ClInclude Include="..\..\dialogxml\dlogevt.hpp" />
|
||||
<ClInclude Include="..\..\dialogxml\dlogutil.buttons.hpp" />
|
||||
<ClInclude Include="..\..\dialogxml\dlogutil.hpp" />
|
||||
<ClInclude Include="..\..\dialogxml\field.hpp" />
|
||||
|
||||
@@ -130,6 +130,9 @@
|
||||
<ClInclude Include="..\..\dialogxml\dialog.keys.hpp">
|
||||
<Filter>DialogXML\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\dialogxml\dlogevt.hpp">
|
||||
<Filter>DialogXML\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\dialogxml\dlogutil.buttons.hpp">
|
||||
<Filter>DialogXML\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -638,6 +638,7 @@
|
||||
915325181A2E37EE000A9A1C /* specials_parse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = specials_parse.cpp; sourceTree = "<group>"; };
|
||||
91597A6C1A3BED2D00BE7BF9 /* spell.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = spell.hpp; sourceTree = "<group>"; };
|
||||
91597A6E1A3BEDC700BE7BF9 /* spell.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spell.cpp; sourceTree = "<group>"; };
|
||||
915AF9E91BC04171008AEF49 /* dlogevt.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = dlogevt.hpp; sourceTree = "<group>"; };
|
||||
915E09071A316D6A008BDF00 /* map_parse.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = map_parse.hpp; sourceTree = "<group>"; };
|
||||
915E09081A316D89008BDF00 /* map_parse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = map_parse.cpp; sourceTree = "<group>"; };
|
||||
9169C31B1B37A5D50041002B /* Blades of Exile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Blades of Exile.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -935,6 +936,7 @@
|
||||
910BBA3B0FB8DA8E001E34EA /* control.hpp */,
|
||||
910BBA170FB8BECA001E34EA /* dialog.hpp */,
|
||||
918D59A718EA513900735B66 /* dialog.keys.hpp */,
|
||||
915AF9E91BC04171008AEF49 /* dlogevt.hpp */,
|
||||
91A32BD10FDB797B00C4E957 /* dlogutil.buttons.hpp */,
|
||||
910BBAD90FB91D2A001E34EA /* dlogutil.hpp */,
|
||||
910BBAB40FB91A26001E34EA /* field.hpp */,
|
||||
|
||||
@@ -23,19 +23,6 @@
|
||||
|
||||
extern sf::Texture bg_gworld;
|
||||
|
||||
void cButton::attachFocusHandler(focus_callback_t) throw(xHandlerNotSupported){
|
||||
throw xHandlerNotSupported(true);
|
||||
}
|
||||
|
||||
void cButton::attachClickHandler(click_callback_t f) throw(){
|
||||
onClick = f;
|
||||
}
|
||||
|
||||
bool cButton::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){
|
||||
if(onClick) return onClick(me,id,mods);
|
||||
return false;
|
||||
}
|
||||
|
||||
cButton::cButton(sf::RenderWindow& parent) :
|
||||
cControl(CTRL_BTN,parent),
|
||||
wrapLabel(false),
|
||||
@@ -59,6 +46,14 @@ bool cButton::isClickable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cButton::isFocusable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cButton::isScrollable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
void cButton::draw(){
|
||||
rectangle from_rect, to_rect;
|
||||
|
||||
@@ -333,41 +328,28 @@ cLed::cLed(cDialog& parent) :
|
||||
textFont(FONT_BOLD),
|
||||
textSize(10) {
|
||||
type = BTN_LED;
|
||||
using namespace std::placeholders;
|
||||
attachEventHandler<EVT_CLICK>(std::bind(&cLed::defaultClickHandler, this, _1, _2, _3));
|
||||
}
|
||||
|
||||
void cLed::attachClickHandler(click_callback_t f) throw(){
|
||||
onClick = f;
|
||||
}
|
||||
|
||||
void cLed::attachFocusHandler(focus_callback_t f) throw(){
|
||||
onFocus = f;
|
||||
}
|
||||
|
||||
bool cLed::triggerFocusHandler(cDialog& me, std::string id, bool losing){
|
||||
if(onFocus != nullptr) return onFocus(me,id,losing);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cLed::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){
|
||||
bool result;
|
||||
eLedState oldState = state;
|
||||
if(onClick != nullptr) result = onClick(me,id,mods);
|
||||
else{ // simple state toggle
|
||||
switch(state){
|
||||
case led_red:
|
||||
case led_green:
|
||||
state = led_off;
|
||||
break;
|
||||
case led_off:
|
||||
state = led_red;
|
||||
}
|
||||
result = true;
|
||||
void cLed::defaultClickHandler(cDialog&, std::string, eKeyMod) {
|
||||
// simple state toggle
|
||||
switch(state){
|
||||
case led_red:
|
||||
case led_green:
|
||||
state = led_off;
|
||||
break;
|
||||
case led_off:
|
||||
state = led_red;
|
||||
}
|
||||
}
|
||||
|
||||
void cLed::callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) {
|
||||
eLedState oldState = state;
|
||||
if(onClick) onClick(me,id,mods);
|
||||
if(!triggerFocusHandler(me,id, oldState != led_off)){
|
||||
result = false;
|
||||
state = oldState;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void cLed::setFormat(eFormat prop, short val) throw(xUnsupportedProp){
|
||||
@@ -453,14 +435,6 @@ void cLedGroup::recalcRect(){
|
||||
frame.inset(-6,-6);
|
||||
}
|
||||
|
||||
void cLedGroup::attachClickHandler(click_callback_t f) throw() {
|
||||
onClick = f;
|
||||
}
|
||||
|
||||
void cLedGroup::attachFocusHandler(focus_callback_t f) throw() {
|
||||
onFocus = f;
|
||||
}
|
||||
|
||||
void cLed::setState(eLedState to){
|
||||
state = to;
|
||||
}
|
||||
@@ -594,17 +568,17 @@ bool cLedGroup::handleClick(location where) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cLedGroup::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){
|
||||
void cLedGroup::callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) {
|
||||
std::string which_clicked = clicking;
|
||||
clicking = "";
|
||||
|
||||
if(choices[which_clicked]->triggerClickHandler(me,which_clicked,mods)){
|
||||
if(onClick && !onClick(me,id,mods)) return false;
|
||||
if(onClick) onClick(me,id,mods);
|
||||
if(!curSelect.empty()) {
|
||||
choices[curSelect]->setState(led_off);
|
||||
if(!choices[curSelect]->triggerFocusHandler(me,curSelect,true)){
|
||||
choices[curSelect]->setState(led_red);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
choices[which_clicked]->setState(led_red);
|
||||
@@ -612,9 +586,9 @@ bool cLedGroup::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){
|
||||
if(!curSelect.empty())
|
||||
choices[curSelect]->setState(led_red);
|
||||
choices[which_clicked]->setState(led_off);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}else return false;
|
||||
}else return;
|
||||
|
||||
std::string savePrevSelect = prevSelect;
|
||||
prevSelect = curSelect;
|
||||
@@ -625,14 +599,20 @@ bool cLedGroup::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){
|
||||
choices[which_clicked]->setState(led_off);
|
||||
curSelect = prevSelect;
|
||||
prevSelect = savePrevSelect;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
bool cLedGroup::triggerFocusHandler(cDialog& me, std::string id, bool losingFocus){
|
||||
if(onFocus != nullptr) return onFocus(me,id,losingFocus);
|
||||
return true;
|
||||
void cLedGroup::attachFocusHandler(std::function<bool(cDialog&,std::string,bool)> f) throw(xHandlerNotSupported) {
|
||||
if(!f) {
|
||||
attachEventHandler<EVT_FOCUS>(nullptr);
|
||||
return;
|
||||
}
|
||||
using namespace std::placeholders;
|
||||
attachEventHandler<EVT_FOCUS>([f](cDialog& me, std::string id) {
|
||||
f(me, id, false);
|
||||
});
|
||||
}
|
||||
|
||||
void cLedGroup::disable(std::string /*id*/) {
|
||||
@@ -676,6 +656,14 @@ bool cLedGroup::isClickable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cLedGroup::isScrollable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cLedGroup::isFocusable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cLedGroup::hasChild(std::string id) {
|
||||
return choices.find(id) != choices.end();
|
||||
}
|
||||
@@ -800,6 +788,11 @@ void cLedGroup::restore(storage_t to) {
|
||||
else setSelected("");
|
||||
}
|
||||
|
||||
void cLedGroup::forEach(std::function<void(std::string,cControl&)> callback) {
|
||||
for(auto ctrl : choices)
|
||||
callback(ctrl.first, *ctrl.second);
|
||||
}
|
||||
|
||||
std::string cLedGroup::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
|
||||
@@ -51,10 +51,6 @@ public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
//virtual void setPict(short pict, short type) = 0;
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
void setColour(sf::Color clr) throw(xUnsupportedProp);
|
||||
@@ -72,15 +68,21 @@ public:
|
||||
/// @param parent The parent window
|
||||
explicit cButton(sf::RenderWindow& parent);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
virtual ~cButton();
|
||||
void draw();
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK};
|
||||
}
|
||||
cButton& operator=(cButton& other) = delete;
|
||||
cButton(cButton& other) = delete;
|
||||
protected:
|
||||
/// The type of button.
|
||||
eBtnType type;
|
||||
/// The click handler.
|
||||
click_callback_t onClick;
|
||||
/// Construct a new button.
|
||||
/// @param parent The parent dialog.
|
||||
/// @param t The type of control. Should be either CTRL_LED or CTRL_BTN.
|
||||
@@ -113,10 +115,6 @@ public:
|
||||
/// @return true to indicate the event should continue.
|
||||
static bool noAction(cDialog&,std::string,eKeyMod) {return true;}
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw();
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
storage_t store();
|
||||
@@ -132,14 +130,21 @@ public:
|
||||
/// @return The current state.
|
||||
eLedState getState();
|
||||
void draw();
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK, EVT_FOCUS, EVT_DEFOCUS};
|
||||
}
|
||||
cLed& operator=(cLed& other) = delete;
|
||||
cLed(cLed& other) = delete;
|
||||
private:
|
||||
void defaultClickHandler(cDialog&, std::string, eKeyMod);
|
||||
void callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) override;
|
||||
eLedState state;
|
||||
eFont textFont;
|
||||
short textSize;
|
||||
static rectangle ledRects[3][2];
|
||||
focus_callback_t onFocus;
|
||||
};
|
||||
|
||||
/// A group of LED buttons that behave like radio buttons.
|
||||
@@ -161,30 +166,29 @@ 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 {
|
||||
click_callback_t onClick;
|
||||
focus_callback_t onFocus;
|
||||
bool drawFramed;
|
||||
bool drawFramed = false;
|
||||
std::map<std::string,cLed*> choices;
|
||||
std::string fromList;
|
||||
std::string curSelect, prevSelect;
|
||||
std::string clicking;
|
||||
void callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) override;
|
||||
cLedGroup& operator=(cLedGroup& other) = delete;
|
||||
cLedGroup(cLedGroup& other) = delete;
|
||||
public:
|
||||
/// @deprecated in favour of @ref attachEventHandler
|
||||
void attachFocusHandler(std::function<bool(cDialog&,std::string,bool)> f) throw(xHandlerNotSupported);
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
/// @copydoc cControl::attachClickHandler()
|
||||
///
|
||||
/// The click handler is called whenever an LED in the group is clicked, even if it's the currently selected LED.
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
/// @copydoc cControl::attachFocusHandler()
|
||||
///
|
||||
/// An LED group triggers focus handlers when a choice other than the currently selected one is clicked.
|
||||
/// The third parameter is always false for an LED group's focus handler.
|
||||
/// You can determine what changed using getPrevSelection() and getSelected(), and can do whatever post-processing
|
||||
/// you want, including selecting a completely different option.
|
||||
void attachFocusHandler(focus_callback_t f) throw();
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus);
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK, EVT_FOCUS};
|
||||
}
|
||||
storage_t store();
|
||||
void restore(storage_t to);
|
||||
/// Add a new LED to this group.
|
||||
@@ -214,6 +218,8 @@ public:
|
||||
/// @param parent The parent dialog.
|
||||
explicit cLedGroup(cDialog& parent);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
bool handleClick(location where);
|
||||
virtual ~cLedGroup();
|
||||
/// Get one of the LEDs in this group.
|
||||
@@ -239,6 +245,7 @@ public:
|
||||
/// Call this after adding choices to the group to ensure that the choice is within the bounding rect.
|
||||
/// If a choice is not within the bounding rect, it will not respond to clicks.
|
||||
void recalcRect();
|
||||
void forEach(std::function<void(std::string,cControl&)> callback) override;
|
||||
/// A convenience type for making an iterator into the choice map.
|
||||
typedef std::map<std::string,cLed*>::iterator ledIter;
|
||||
void draw();
|
||||
|
||||
@@ -37,15 +37,19 @@ void cControl::relocate(location to) {
|
||||
frame.offset(to.x - frame.left, to.y - frame.top);
|
||||
}
|
||||
|
||||
const char* xHandlerNotSupported::focusMsg = "This control cannot handle focus events.\n";
|
||||
const char* xHandlerNotSupported::clickMsg = "This control cannot handle click events.\n";
|
||||
const char* xHandlerNotSupported::msg[4] = {
|
||||
"This control cannot handle click events.\n",
|
||||
"This control cannot handle focus events.\n",
|
||||
"This control cannot handle defocus events.\n",
|
||||
"This control cannot handle scroll events.\n",
|
||||
};
|
||||
|
||||
xHandlerNotSupported::xHandlerNotSupported(bool isFocus){
|
||||
this->isFocus = isFocus;
|
||||
xHandlerNotSupported::xHandlerNotSupported(eDlogEvt t){
|
||||
this->evt = t;
|
||||
}
|
||||
const char* xHandlerNotSupported::what() const throw() {
|
||||
if(isFocus) return focusMsg;
|
||||
else return clickMsg;
|
||||
assert("A handler not supported message is missing!" && evt < 4);
|
||||
return msg[evt];
|
||||
}
|
||||
|
||||
xUnsupportedProp::xUnsupportedProp(eFormat prop) throw(){
|
||||
@@ -268,11 +272,38 @@ cControl::cControl(eControlType t, cDialog& p) : parent(&p), inWindow(&p.win), t
|
||||
|
||||
cControl::cControl(eControlType t, sf::RenderWindow& p) : parent(nullptr), inWindow(&p), type(t), visible(true), key({false, 0, mod_none}), frameStyle(FRM_INSET) {}
|
||||
|
||||
bool cControl::triggerClickHandler(cDialog&, std::string, eKeyMod){
|
||||
|
||||
void cControl::attachClickHandler(std::function<bool(cDialog&,std::string,eKeyMod)> f) throw(xHandlerNotSupported) {
|
||||
if(!f) {
|
||||
attachEventHandler<EVT_CLICK>(nullptr);
|
||||
return;
|
||||
}
|
||||
attachEventHandler<EVT_CLICK>([f](cDialog& me, std::string id, eKeyMod mods) {
|
||||
f(me, id, mods);
|
||||
});
|
||||
}
|
||||
|
||||
void cControl::attachFocusHandler(std::function<bool(cDialog&,std::string,bool)> f) throw(xHandlerNotSupported) {
|
||||
if(!f) {
|
||||
attachEventHandler<EVT_FOCUS>(nullptr);
|
||||
attachEventHandler<EVT_DEFOCUS>(nullptr);
|
||||
return;
|
||||
}
|
||||
using namespace std::placeholders;
|
||||
attachEventHandler<EVT_FOCUS>([f](cDialog& me, std::string id) {
|
||||
f(me, id, false);
|
||||
});
|
||||
attachEventHandler<EVT_DEFOCUS>(std::bind(f, _1, _2, true));
|
||||
}
|
||||
|
||||
bool cControl::triggerClickHandler(cDialog& dlg, std::string id, eKeyMod mods){
|
||||
triggerEvent<EVT_CLICK>(dlg, id, mods);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cControl::triggerFocusHandler(cDialog&, std::string, bool){
|
||||
bool cControl::triggerFocusHandler(cDialog& dlg, std::string id, bool losing){
|
||||
if(losing) return triggerEvent<EVT_DEFOCUS>(dlg, id);
|
||||
triggerEvent<EVT_FOCUS>(dlg, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,23 +17,19 @@
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <boost/any.hpp>
|
||||
#include "dialog.hpp"
|
||||
|
||||
#include "location.hpp"
|
||||
|
||||
//struct cPict {
|
||||
// short pict;
|
||||
// short type;
|
||||
//};
|
||||
|
||||
/// Formatting properties
|
||||
enum eFormat {
|
||||
TXT_FRAME, ///< Whether to draw a frame around the control. Should be a boolean (true or false).
|
||||
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 @a eFrameStyle.
|
||||
TXT_FRAMESTYLE, ///< The control's frame style. Should be an enum from @ref eFrameStyle.
|
||||
};
|
||||
|
||||
/// Frame styles
|
||||
@@ -58,20 +54,14 @@ enum eControlType {
|
||||
CTRL_PANE, ///< A scroll pane
|
||||
};
|
||||
|
||||
/// The signature of a click handler.
|
||||
typedef std::function<bool(cDialog&,std::string,eKeyMod)> click_callback_t;
|
||||
/// The signature of a focus handler.
|
||||
typedef std::function<bool(cDialog&,std::string,bool)> focus_callback_t;
|
||||
|
||||
/// Thrown when you try to set a handler that the control does not support.
|
||||
class xHandlerNotSupported : public std::exception {
|
||||
static const char* focusMsg;
|
||||
static const char* clickMsg;
|
||||
bool isFocus;
|
||||
static const char* msg[4];
|
||||
eDlogEvt evt;
|
||||
public:
|
||||
/// Construct a new exception.
|
||||
/// @param isFocus true to indicate a focus event, false for a click event.
|
||||
xHandlerNotSupported(bool isFocus);
|
||||
/// @param t The type of event.
|
||||
xHandlerNotSupported(eDlogEvt t);
|
||||
/// @return The error message.
|
||||
const char* what() const throw();
|
||||
};
|
||||
@@ -117,37 +107,72 @@ public:
|
||||
/// @return the currently-assigned keyboard shortcut.
|
||||
/// @note You should first check that a shortcut is assigned using hasKey().
|
||||
cKey getAttachedKey();
|
||||
/// 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.
|
||||
/// @return The previous handler that has been overridden, if any.
|
||||
/// @throw xHandlerNotSupported if the event type is not supported by this control.
|
||||
/// @note Only one handler can be set at a time for any given event. To remove a handler, set it to nullptr.
|
||||
template<eDlogEvt t> typename event_fcn<t>::type attachEventHandler(typename event_fcn<t>::type handler) {
|
||||
if(getSupportedHandlers().count(t) == 0) throw xHandlerNotSupported(t);
|
||||
auto old_handler = event_handlers[t];
|
||||
if(handler) event_handlers[t] = handler;
|
||||
else event_handlers[t].clear();
|
||||
if(old_handler.empty()) return nullptr;
|
||||
return boost::any_cast<typename event_fcn<t>::type>(old_handler);
|
||||
}
|
||||
/// Attach a click handler to this control.
|
||||
/// @param f The click handler to attach.
|
||||
/// @throw xHandlerNotSupported if this control does not support click handlers. Most controls do support click handlers.
|
||||
/// @deprecated in favour of @ref attachEventHandler
|
||||
/// @note Only one click handler can be set at a time. To remove the click handler, set it to null.
|
||||
///
|
||||
/// A click handler must be able to accept three parameters: a reference to the containing dialog, the unique key of the
|
||||
/// clicked item, and a representation of any modifier keys that are currently held.
|
||||
virtual void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) = 0;
|
||||
virtual void attachClickHandler(std::function<bool(cDialog&,std::string,eKeyMod)> f) throw(xHandlerNotSupported);
|
||||
/// Attach a focus handler to this control.
|
||||
/// @param f The focus handler to attach.
|
||||
/// @throw xHandlerNotSupported if this control does not support focus handlers. Most controls do not support focus handlers.
|
||||
/// @deprecated in favour of @ref attachEventHandler
|
||||
/// @note Only one focus handler can be set at a time. To remove the focus handler, set it to null.
|
||||
///
|
||||
/// A focus handler must be able to accept three parameters: a reference to the containing dialog, the unique key of the
|
||||
/// clicked item, and a boolean indicating whether focus is being lost or gained; a value of true indicates that
|
||||
/// focus is being lost, while false indicates it's being gained. Most handlers will only need to act when the
|
||||
/// third parameter is true. If the handler returns false, the focus change is cancelled.
|
||||
virtual void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported) = 0;
|
||||
virtual void attachFocusHandler(std::function<bool(cDialog&,std::string,bool)> f) throw(xHandlerNotSupported);
|
||||
/// Trigger an event on this control.
|
||||
/// @tparam t The type of event to trigger.
|
||||
/// @tparam Params Additional parameters, depending on the event type.
|
||||
/// @param dlg The parent dialog of this control.
|
||||
/// @param args Additional arguments, depending on the event type.
|
||||
/// @return The result of the event handler. If there was no handler, and the handler would've returned a bool,
|
||||
/// then true is returned. This also applies if the event type is not supported by the control.
|
||||
template<eDlogEvt t, typename... Params> typename event_fcn<t>::type::result_type triggerEvent(cDialog& dlg, Params... args) {
|
||||
using fcn_t = typename event_fcn<t>::type;
|
||||
if(event_handlers[t].empty())
|
||||
return callHandler(fcn_t(), dlg, args...);
|
||||
auto handler = boost::any_cast<fcn_t>(event_handlers[t]);
|
||||
return callHandler(handler, dlg, args...);
|
||||
}
|
||||
/// Check if a handler is assigned for a given event.
|
||||
/// @param t The type of event to check for.
|
||||
/// @return True if one is assigned, false otherwise.
|
||||
bool haveHandler(eDlogEvt t) {
|
||||
return !event_handlers[t].empty();
|
||||
}
|
||||
/// Trigger the click handler for this control.
|
||||
/// @param me A reference to the current dialog.
|
||||
/// @param id The unique key of this control.
|
||||
/// @param mods The currently-held keyboard modifiers.
|
||||
/// @return true if the event should continue, false if it should be cancelled.
|
||||
virtual bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
virtual bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods) final;
|
||||
/// Trigger the focus handler for this control.
|
||||
/// @param me A reference to the current dialog.
|
||||
/// @param id The unique key of this control.
|
||||
/// @param losingFocus true if this control is losing focus, false if it is gaining focus.
|
||||
/// @return true if the event should continue, false if it should be cancelled.
|
||||
virtual bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus);
|
||||
//virtual void setPict(short pict, short type) = 0;
|
||||
virtual bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus) final;
|
||||
/// Make this control visible.
|
||||
virtual void show(); // cd_activate_item true
|
||||
/// Make this control invisible.
|
||||
@@ -157,6 +182,8 @@ public:
|
||||
bool isVisible(); // cd_get_active
|
||||
/// Check if this control is a container which contains other controls.
|
||||
/// @return true if it's a container
|
||||
/// @note Generally you shouldn't override this. If you need a container, then
|
||||
/// extend @ref cContainer instead of cControl.
|
||||
virtual bool isContainer() {return false;}
|
||||
/// Set if this control is active. A control is normally active when the mouse button is held down within its bounding rect.
|
||||
/// @param active true if it should be active, false if not
|
||||
@@ -209,6 +236,14 @@ public:
|
||||
/// In fact, some controls return true only if a click handler is assigned.
|
||||
/// Others, like editable text fields, are clickable but do not support click handlers.
|
||||
virtual bool isClickable() = 0;
|
||||
/// Check if the control is focusable.
|
||||
/// @return true if it's focusable.
|
||||
/// @note This does not indicate whether the control supports focus and defocus handlers.
|
||||
virtual bool isFocusable() = 0;
|
||||
/// Check if the control is scrollable.
|
||||
/// @return true if it's scrollable.
|
||||
/// @note This does not indicate whether the control supports scroll handlers.
|
||||
virtual bool isScrollable() = 0;
|
||||
/// Handles the action of clicking this control.
|
||||
/// @param where The exact location at which the mouse was pressed, relative to the dialog.
|
||||
/// @return true if the click was successful; false if it was cancelled.
|
||||
@@ -243,6 +278,54 @@ public:
|
||||
cControl& operator=(cControl& other) = delete;
|
||||
cControl(cControl& other) = delete;
|
||||
protected:
|
||||
/// Returns a list of event handlers that this control supports.
|
||||
/// @return The list of handlers as a std::set.
|
||||
///
|
||||
/// See the documentation of this method in subclasses for explanations of what handlers
|
||||
/// each control supports and how those handlers work for that control.
|
||||
virtual const std::set<eDlogEvt> getSupportedHandlers() const = 0;
|
||||
/// Called when a click event is triggered on this control. Override this to
|
||||
/// customize the behaviour of clicks on the control. Note that, if you override it, you are
|
||||
/// responsible for calling the passed handler, if it exists. (Test for existance with operator!.)
|
||||
/// @param handler The handler that should be triggered as a result of this click.
|
||||
/// @param dlg The dialog in which the event was triggered; intended to be passed to the handler.
|
||||
/// @param id The ID of the control that triggered the event; intended to be passed to the handler.
|
||||
/// @param mods The key modifiers currently pressed; intended to be passed to the handler.
|
||||
virtual void callHandler(event_fcn<EVT_CLICK>::type handler, cDialog& dlg, std::string id, eKeyMod mods) {
|
||||
if(handler) handler(dlg, id, mods);
|
||||
}
|
||||
/// Called when a focus event is triggered on this control. Override this to
|
||||
/// customize the behaviour of focusing on the control. Note that, if you override it, you are
|
||||
/// responsible for calling the passed handler, if it exists. (Test for existance with operator!.)
|
||||
/// @param handler The handler that should be triggered as a result of this focus.
|
||||
/// @param dlg The dialog in which the event was triggered; intended to be passed to the handler.
|
||||
/// @param id The ID of the control that triggered the event; intended to be passed to the handler.
|
||||
virtual void callHandler(event_fcn<EVT_FOCUS>::type handler, cDialog& dlg, std::string id) {
|
||||
if(handler) handler(dlg, id);
|
||||
}
|
||||
/// Called when a defocus event is triggered on this control. Override this to
|
||||
/// customize the behaviour of defocusing on the control. Note that, if you override it, you are
|
||||
/// responsible for calling the passed handler, if it exists. (Test for existance with operator!.)
|
||||
/// @param handler The handler that should be triggered as a result of this defocus.
|
||||
/// @param dlg The dialog in which the event was triggered; intended to be passed to the handler.
|
||||
/// @param id The ID of the control that triggered the event; intended to be passed to the handler.
|
||||
/// @return Whether the defocus should be allowed to happen.
|
||||
virtual bool callHandler(event_fcn<EVT_DEFOCUS>::type handler, cDialog& dlg, std::string id) {
|
||||
if(handler) return handler(dlg, id);
|
||||
return true;
|
||||
}
|
||||
/// Called when a scroll event is triggered on this control. Override this to
|
||||
/// customize the behaviour of scrolling on the control. Note that, if you override it, you are
|
||||
/// responsible for calling the passed handler, if it exists. (Test for existance with operator!.)
|
||||
/// @param handler The handler that should be triggered as a result of this scroll.
|
||||
/// @param dlg The dialog in which the event was triggered; intended to be passed to the handler.
|
||||
/// @param id The ID of the control that triggered the event; intended to be passed to the handler.
|
||||
/// @param newVal The new value of the scrollbar.
|
||||
/// @return Whether the scrollbar should be allowed to scroll to this point.
|
||||
virtual bool callHandler(event_fcn<EVT_SCROLL>::type handler, cDialog& dlg, std::string id, int newVal) {
|
||||
if(handler) return handler(dlg, id, newVal);
|
||||
return true;
|
||||
}
|
||||
/// Parses an HTML colour code.
|
||||
/// Recognizes three-digit hex, six-digit hex, and HTML colour names.
|
||||
/// @param code The colour code to parse.
|
||||
@@ -282,9 +365,13 @@ protected:
|
||||
private:
|
||||
friend class cDialog; // TODO: This is only so it can access parseColour... hack!
|
||||
eControlType type;
|
||||
std::map<eDlogEvt, boost::any> event_handlers;
|
||||
};
|
||||
|
||||
/// A superclass to represent a control that contains other controls.
|
||||
class cContainer : public cControl {
|
||||
void callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) override;
|
||||
std::string clicking;
|
||||
public:
|
||||
/// Create a new container control attached to an arbitrary window, rather than a dialog.
|
||||
/// @param t The type of the control.
|
||||
@@ -303,9 +390,23 @@ public:
|
||||
/// @throw std::invalid_argument if the control does not exist.
|
||||
/// @return a reference to the requested control.
|
||||
virtual cControl& getChild(std::string id) = 0;
|
||||
/// Executes a function for every control in this container.
|
||||
/// @param callback A function taking a string as its first argument
|
||||
/// and a control reference as its second argument.
|
||||
virtual void forEach(std::function<void(std::string,cControl&)> callback) = 0;
|
||||
/// @copydoc getChild()
|
||||
cControl& operator[](std::string id) {return getChild(id);}
|
||||
bool isContainer() {return true;}
|
||||
bool handleClick(location where);
|
||||
};
|
||||
|
||||
// This is defined here instead of in dialog.hpp because it needs cControl to be complete.
|
||||
/// @note You need to include control.hpp to use this.
|
||||
template<eDlogEvt t> void cDialog::attachEventHandlers(typename event_fcn<t>::type handler, const std::vector<std::string>& controls) {
|
||||
cDialog& me = *this;
|
||||
for(std::string control : controls) {
|
||||
me[control].attachEventHandler<t>(handler);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -508,9 +508,7 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
key.mod += mod_ctrl;
|
||||
if(currentEvent.key.shift) key.mod += mod_shift;
|
||||
if(currentEvent.key.alt) key.mod += mod_alt;
|
||||
itemHit = process_keystroke(key);
|
||||
if(!itemHit.empty())
|
||||
where = controls[itemHit]->getBounds().centre();
|
||||
process_keystroke(key);
|
||||
// Now check for focused fields.
|
||||
if(currentFocus.empty()) break;
|
||||
// If it's a tab, handle tab order
|
||||
@@ -547,7 +545,7 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
if(kb::isKeyPressed(kb::LShift)) key.mod += mod_shift;
|
||||
if(kb::isKeyPressed(kb::RShift)) key.mod += mod_shift;
|
||||
where = {currentEvent.mouseButton.x, currentEvent.mouseButton.y};
|
||||
itemHit = process_click(where);
|
||||
process_click(where, key.mod);
|
||||
break;
|
||||
default: // To silence warning of unhandled enum values
|
||||
break;
|
||||
@@ -564,11 +562,6 @@ void cDialog::run(std::function<void(cDialog&)> onopen){
|
||||
if(!inField) set_cursor(sword_curs);
|
||||
break;
|
||||
}
|
||||
if(itemHit.empty()) continue;;
|
||||
ctrlIter ctrl = controls.find(itemHit);
|
||||
// TODO: Should it do something with the boolean return value?
|
||||
if(ctrl != controls.end()) ctrl->second->triggerClickHandler(*this,itemHit,key.mod);
|
||||
itemHit.clear();
|
||||
}
|
||||
win.setVisible(false);
|
||||
while(parentWin->pollEvent(currentEvent));
|
||||
@@ -589,7 +582,7 @@ template<typename Iter> void cDialog::handleTabOrder(string& itemHit, Iter begin
|
||||
while(iter != cur){
|
||||
// If tab order is explicitly specified for all fields, gaps are possible
|
||||
if(iter->second == nullptr) continue;
|
||||
if(iter->second->getType() == CTRL_FIELD && iter->second->isVisible()){
|
||||
if(iter->second->isFocusable() && iter->second->isVisible()){
|
||||
if(iter->second->triggerFocusHandler(*this,iter->first,false)){
|
||||
currentFocus = iter->first;
|
||||
}
|
||||
@@ -660,14 +653,14 @@ cTextField* cDialog::getFocus() {
|
||||
return dynamic_cast<cTextField*>(iter->second);
|
||||
}
|
||||
|
||||
void cDialog::attachClickHandlers(click_callback_t handler, std::vector<std::string> controls) {
|
||||
void cDialog::attachClickHandlers(std::function<bool(cDialog&,std::string,eKeyMod)> handler, std::vector<std::string> controls) {
|
||||
cDialog& me = *this;
|
||||
for(std::string control : controls) {
|
||||
me[control].attachClickHandler(handler);
|
||||
}
|
||||
}
|
||||
|
||||
void cDialog::attachFocusHandlers(focus_callback_t handler, std::vector<std::string> controls) {
|
||||
void cDialog::attachFocusHandlers(std::function<bool(cDialog&,std::string,bool)> handler, std::vector<std::string> controls) {
|
||||
cDialog& me = *this;
|
||||
for(std::string control : controls) {
|
||||
me[control].attachFocusHandler(handler);
|
||||
@@ -716,7 +709,7 @@ bool cDialog::addLabelFor(std::string key, std::string label, eLabelPos where, s
|
||||
return add(labelCtrl, labelRect, key);
|
||||
}
|
||||
|
||||
std::string cDialog::process_keystroke(cKey keyHit){
|
||||
void cDialog::process_keystroke(cKey keyHit){
|
||||
ctrlIter iter = controls.begin();
|
||||
while(iter != controls.end()){
|
||||
if(iter->second->isVisible() && iter->second->isClickable() && iter->second->getAttachedKey() == keyHit){
|
||||
@@ -732,31 +725,32 @@ std::string cDialog::process_keystroke(cKey keyHit){
|
||||
iter->second->setActive(false);
|
||||
draw();
|
||||
sf::sleep(sf::milliseconds(8));
|
||||
return iter->first;
|
||||
iter->second->triggerClickHandler(*this,iter->first,mod_none);
|
||||
return;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
// If you get an escape and it isn't processed, make it an enter.
|
||||
if(keyHit.spec && keyHit.k == key_esc){
|
||||
keyHit.k = key_enter;
|
||||
return process_keystroke(keyHit);
|
||||
process_keystroke(keyHit);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string cDialog::process_click(location where){
|
||||
void cDialog::process_click(location where, eKeyMod mods){
|
||||
// TODO: Return list of all controls whose bounding rect contains the clicked point.
|
||||
// Then the return value of the click handler can mean "Don't pass this event on to other things below me".
|
||||
ctrlIter iter = controls.begin();
|
||||
while(iter != controls.end()){
|
||||
if(iter->second->isVisible() && iter->second->isClickable() && where.in(iter->second->getBounds())){
|
||||
if(iter->second->handleClick(where))
|
||||
return iter->first;
|
||||
else return "";
|
||||
break;
|
||||
else return;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
return "";
|
||||
if(iter != controls.end())
|
||||
iter->second->triggerClickHandler(*this,iter->first,mods);
|
||||
}
|
||||
|
||||
xBadNode::xBadNode(std::string t, int r, int c, std::string dlg) throw() :
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "ticpp.h"
|
||||
#include "dialog.keys.hpp"
|
||||
#include "dlogevt.hpp"
|
||||
#include "location.hpp"
|
||||
#include <boost/any.hpp>
|
||||
|
||||
@@ -161,6 +162,12 @@ public:
|
||||
/// Recalculate the dialog's bounding rect.
|
||||
/// Call this after adding controls to the dialog to ensure that the control is within the bounding rect.
|
||||
void recalcRect();
|
||||
/// Attach the same handler for a given event to several controls.
|
||||
/// @tparam t The type of event to attach handlers for.
|
||||
/// @param controls A list of control IDs to attach the handlers to.
|
||||
/// @throw xHandlerNotSupported if any of the controls do not support this event type.
|
||||
/// In this event, any subsequent controls in the list will not have had the handlers attached.
|
||||
template<eDlogEvt t> void attachEventHandlers(typename event_fcn<t>::type handler, const std::vector<std::string>& controls);
|
||||
// TODO: It seems like a bad thing for these two to not use the typedefs...
|
||||
/// Attach the same click handler to several controls.
|
||||
/// @param handler The handler to attach.
|
||||
@@ -168,6 +175,7 @@ public:
|
||||
/// @throw xHandlerNotSupported if any of the controls do not support click handlers.
|
||||
/// @throw std::invalid_argument if any of the controls do not exist.
|
||||
/// @see cControl::attachClickHandler()
|
||||
/// @deprecated in favour of @ref attachEventHandlers
|
||||
void attachClickHandlers(std::function<bool(cDialog&,std::string,eKeyMod)> handler, std::vector<std::string> controls);
|
||||
/// Attach the same focus handler to several controls.
|
||||
/// @param handler The handler to attach.
|
||||
@@ -175,6 +183,7 @@ public:
|
||||
/// @throw xHandlerNotSupported if any of the controls do not support focus handlers.
|
||||
/// @throw std::invalid_argument if any of the controls do not exist.
|
||||
/// @see cControl::attachFocusHandler()
|
||||
/// @deprecated in favour of @ref attachEventHandlers
|
||||
void attachFocusHandlers(std::function<bool(cDialog&,std::string,bool)> handler, std::vector<std::string> controls);
|
||||
/// Get the bounding rect of the dialog.
|
||||
/// @return The dialog's bounding rect.
|
||||
@@ -205,8 +214,8 @@ public:
|
||||
cDialog(cDialog& other) = delete;
|
||||
private:
|
||||
void draw();
|
||||
std::string process_keystroke(cKey keyHit);
|
||||
std::string process_click(location where);
|
||||
void process_keystroke(cKey keyHit);
|
||||
void process_click(location where, eKeyMod mods);
|
||||
bool dialogNotToast, didAccept;
|
||||
rectangle winRect;
|
||||
boost::any result;
|
||||
|
||||
71
src/dialogxml/dlogevt.hpp
Normal file
71
src/dialogxml/dlogevt.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// dlogevt.hpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 15-10-03.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef BoE_dlogevt_hpp
|
||||
#define BoE_dlogevt_hpp
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include "dialog.keys.hpp"
|
||||
|
||||
/// Represents an event that can occur in a dialog.
|
||||
enum eDlogEvt {
|
||||
EVT_CLICK, ///< A click event - the mouse has been pressed and released.
|
||||
EVT_FOCUS, ///< A focus event - a control has gained focus.
|
||||
EVT_DEFOCUS, ///< A defocus event - a control is losing focus.
|
||||
EVT_SCROLL, ///< A scroll event - a control has changed in response to the mouse wheel.
|
||||
};
|
||||
|
||||
/// A metafunction to obtain the signature of a handler for a given event.
|
||||
/// The first parameter is always cDialog& and the second paramater is
|
||||
/// usually std::string. Return type and additional parameters, if any,
|
||||
/// may vary.
|
||||
/// @tparam t The type of event you need a handler for.
|
||||
/// @return An std::function type representing the even handler
|
||||
/// as member type.
|
||||
template<eDlogEvt t> struct event_fcn;
|
||||
class cDialog;
|
||||
|
||||
/// @typedef type
|
||||
/// @memberof event_fcn
|
||||
/// @brief The return value; an std::function instantiation.
|
||||
|
||||
/// Specialization of event_fcn for EVT_CLICK.
|
||||
template<> struct event_fcn<EVT_CLICK> {
|
||||
/// The signature for a click event handler.
|
||||
/// Requires the dialog, the ID of the clicked element, and the current modifier key state.
|
||||
/// Returns nothing.
|
||||
using type = std::function<void(cDialog&, std::string, eKeyMod)>;
|
||||
};
|
||||
|
||||
/// Specialization of event_fcn for EVT_FOCUS.
|
||||
template<> struct event_fcn<EVT_FOCUS> {
|
||||
/// The signature for a focus event handler.
|
||||
/// Requires only the dialog and the ID of the clicked element.
|
||||
/// Returns nothing.
|
||||
using type = std::function<void(cDialog&, std::string)>;
|
||||
};
|
||||
|
||||
/// Specialization of event_fcn for EVT_DEFOCUS.
|
||||
template<> struct event_fcn<EVT_DEFOCUS> {
|
||||
/// The signature of a defocus event handler.
|
||||
/// Requires only the dialog and the ID of the clicked element.
|
||||
/// Returns false if defocus should be cancelled.
|
||||
using type = std::function<bool(cDialog&, std::string)>;
|
||||
};
|
||||
|
||||
/// Specialization of event_fcn for EVT_SCROLL.
|
||||
template<> struct event_fcn<EVT_SCROLL> {
|
||||
/// The signature of a scroll event handler.
|
||||
/// Requires the dialog, the ID of the clicked element, and the resulting value.
|
||||
/// Returns false if scrolling should be cancelled.
|
||||
using type = std::function<bool(cDialog&, std::string, int)>;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,16 +17,8 @@
|
||||
#include "winutil.hpp"
|
||||
#include "cursors.hpp"
|
||||
|
||||
void cTextField::attachClickHandler(click_callback_t) throw(xHandlerNotSupported){
|
||||
throw xHandlerNotSupported(false);
|
||||
}
|
||||
|
||||
void cTextField::attachFocusHandler(focus_callback_t f) throw(){
|
||||
onFocus = f;
|
||||
}
|
||||
|
||||
bool cTextField::triggerFocusHandler(cDialog& me, std::string id, bool losingFocus){
|
||||
if(losingFocus && field_type != FLD_TEXT) {
|
||||
bool cTextField::callHandler(event_fcn<EVT_DEFOCUS>::type onFocus, cDialog& me, std::string id) {
|
||||
if(field_type != FLD_TEXT) {
|
||||
try {
|
||||
std::string contents = getText();
|
||||
switch(field_type) {
|
||||
@@ -52,13 +44,20 @@ bool cTextField::triggerFocusHandler(cDialog& me, std::string id, bool losingFoc
|
||||
}
|
||||
}
|
||||
bool passed = true;
|
||||
if(onFocus != nullptr) passed = onFocus(me,id,losingFocus);
|
||||
if(passed) haveFocus = !losingFocus;
|
||||
if(onFocus) passed = onFocus(me,id);
|
||||
if(passed) haveFocus = false;
|
||||
if(haveFocus && insertionPoint < 0)
|
||||
insertionPoint = getText().length();
|
||||
return passed;
|
||||
}
|
||||
|
||||
void cTextField::callHandler(event_fcn<EVT_FOCUS>::type onFocus, cDialog& me, std::string id) {
|
||||
if(onFocus) onFocus(me,id);
|
||||
haveFocus = true;
|
||||
if(insertionPoint < 0)
|
||||
insertionPoint = getText().length();
|
||||
}
|
||||
|
||||
void cTextField::setText(std::string to) {
|
||||
cControl::setText(to);
|
||||
if(haveFocus)
|
||||
@@ -193,6 +192,14 @@ bool cTextField::isClickable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cTextField::isFocusable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cTextField::isScrollable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cTextField::hasFocus() {
|
||||
return haveFocus;
|
||||
}
|
||||
|
||||
@@ -34,11 +34,13 @@ enum eFldType {
|
||||
class cTextField : public cControl {
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
|
||||
/// @copydoc cControl::attachFocusHandler()
|
||||
/// For text fields, this is triggered when it loses or gains the input focus.
|
||||
void attachFocusHandler(focus_callback_t f) throw();
|
||||
bool triggerFocusHandler(cDialog& me, std::string id, bool losingFocus);
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_FOCUS, EVT_DEFOCUS};
|
||||
}
|
||||
bool handleClick(location where);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
@@ -57,6 +59,8 @@ public:
|
||||
/// @param parent The parent dialog.
|
||||
explicit cTextField(cDialog& parent);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
virtual ~cTextField();
|
||||
void draw();
|
||||
/// Check if this text field currently has input focus.
|
||||
@@ -70,11 +74,12 @@ public:
|
||||
/// This field is only used by cDialog during the loading process. Changing it will have no effect.
|
||||
long tabOrder = 0;
|
||||
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;
|
||||
void set_ip(location clickLoc, int cTextField::* insertionPoint);
|
||||
cUndoList history;
|
||||
action_ptr current_action;
|
||||
eFldType field_type;
|
||||
focus_callback_t onFocus;
|
||||
bool haveFocus;
|
||||
int insertionPoint;
|
||||
int selectionPoint;
|
||||
|
||||
@@ -13,20 +13,6 @@
|
||||
|
||||
extern sf::Texture bg_gworld;
|
||||
|
||||
void cTextMsg::attachClickHandler(click_callback_t f) throw(){
|
||||
onClick = f;
|
||||
clickable = onClick != nullptr;
|
||||
}
|
||||
|
||||
void cTextMsg::attachFocusHandler(focus_callback_t) throw(xHandlerNotSupported){
|
||||
throw xHandlerNotSupported(true);
|
||||
}
|
||||
|
||||
bool cTextMsg::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){
|
||||
if(onClick != nullptr) return onClick(me,id,mods);
|
||||
return false;
|
||||
}
|
||||
|
||||
void cTextMsg::setColour(sf::Color clr) throw(xUnsupportedProp) {
|
||||
color = clr;
|
||||
}
|
||||
@@ -179,7 +165,6 @@ cTextMsg::cTextMsg(cDialog& parent) :
|
||||
textFont(FONT_BOLD),
|
||||
textSize(10),
|
||||
color(parent.getDefTextClr()),
|
||||
clickable(false),
|
||||
fromList("none") {}
|
||||
|
||||
cTextMsg::cTextMsg(sf::RenderWindow& parent) :
|
||||
@@ -188,11 +173,18 @@ cTextMsg::cTextMsg(sf::RenderWindow& parent) :
|
||||
textFont(FONT_BOLD),
|
||||
textSize(10),
|
||||
color(cDialog::defaultBackground == cDialog::BG_DARK ? sf::Color::White : sf::Color::Black),
|
||||
clickable(false),
|
||||
fromList("none") {}
|
||||
|
||||
bool cTextMsg::isClickable(){
|
||||
return clickable;
|
||||
return haveHandler(EVT_CLICK);
|
||||
}
|
||||
|
||||
bool cTextMsg::isFocusable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cTextMsg::isScrollable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
void cTextMsg::draw(){
|
||||
@@ -206,7 +198,7 @@ void cTextMsg::draw(){
|
||||
style.pointSize = textSize;
|
||||
if(drawFramed) drawFrame(2,frameStyle);
|
||||
sf::Color draw_color = color;
|
||||
if(clickable && depressed){
|
||||
if(depressed){
|
||||
draw_color.r = 256 - draw_color.r;
|
||||
draw_color.g = 256 - draw_color.g;
|
||||
draw_color.b = 256 - draw_color.b;
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
class cTextMsg : public cControl {
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
void setColour(sf::Color clr) throw(xUnsupportedProp);
|
||||
@@ -37,16 +34,23 @@ public:
|
||||
/// @param parent The parent window.
|
||||
explicit cTextMsg(sf::RenderWindow& parent);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
virtual ~cTextMsg();
|
||||
void draw();
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK};
|
||||
}
|
||||
cTextMsg& operator=(cTextMsg& other) = delete;
|
||||
cTextMsg(cTextMsg& other) = delete;
|
||||
private:
|
||||
bool drawFramed, clickable;
|
||||
bool drawFramed;
|
||||
short textSize;
|
||||
eFont textFont;
|
||||
sf::Color color;
|
||||
std::string fromList;
|
||||
click_callback_t onClick;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -70,25 +70,6 @@ std::map<ePicType,void(cPict::*)(short,rectangle)>& cPict::drawPict(){
|
||||
return f;
|
||||
}
|
||||
|
||||
void cPict::attachClickHandler(click_callback_t f) throw(){
|
||||
if(f == nullptr){
|
||||
onClick = nullptr;
|
||||
clickable = false;
|
||||
}else{
|
||||
onClick = f;
|
||||
clickable = true;
|
||||
}
|
||||
}
|
||||
|
||||
void cPict::attachFocusHandler(focus_callback_t) throw(xHandlerNotSupported){
|
||||
throw xHandlerNotSupported(true);
|
||||
}
|
||||
|
||||
bool cPict::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods){
|
||||
if(onClick != nullptr) return onClick(me,id,mods);
|
||||
else return false;
|
||||
}
|
||||
|
||||
void cPict::setFormat(eFormat prop, short val) throw(xUnsupportedProp){
|
||||
if(prop == TXT_FRAME) drawFramed = val;
|
||||
else if(prop == TXT_FRAMESTYLE) frameStyle = eFrameStyle(val);
|
||||
@@ -148,16 +129,22 @@ ePicType cPict::getPicType(){
|
||||
|
||||
cPict::cPict(cDialog& parent) :
|
||||
cControl(CTRL_PICT,parent),
|
||||
drawFramed(true),
|
||||
clickable(false) {}
|
||||
drawFramed(true) {}
|
||||
|
||||
cPict::cPict(sf::RenderWindow& parent) :
|
||||
cControl(CTRL_PICT, parent),
|
||||
drawFramed(true),
|
||||
clickable(false) {}
|
||||
drawFramed(true) {}
|
||||
|
||||
bool cPict::isClickable(){
|
||||
return clickable;
|
||||
return haveHandler(EVT_CLICK);
|
||||
}
|
||||
|
||||
bool cPict::isFocusable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cPict::isScrollable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
ePicType operator+ (ePicType lhs, ePicTypeMod rhs){
|
||||
|
||||
@@ -26,9 +26,6 @@ public:
|
||||
/// @copydoc cDialog::init()
|
||||
static void init();
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw();
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
void setColour(sf::Color clr) throw(xUnsupportedProp);
|
||||
@@ -66,6 +63,8 @@ public:
|
||||
/// @param parent The parent window.
|
||||
explicit cPict(sf::RenderWindow& parent);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
/// Advance the current animation frame.
|
||||
/// Should be called at predictable intervals if the dialog might contain an animated graphic.
|
||||
static void advanceAnim();
|
||||
@@ -81,6 +80,12 @@ public:
|
||||
/// A convenience constant that can be passed as the pic number to setPict(pic_num_t num).
|
||||
/// It sets the icon to nothing, showing as just black.
|
||||
static const pic_num_t BLANK;
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK};
|
||||
}
|
||||
cPict& operator=(cPict& other) = delete;
|
||||
cPict(cPict& other) = delete;
|
||||
private:
|
||||
@@ -88,7 +93,7 @@ private:
|
||||
static short animFrame;
|
||||
pic_num_t picNum;
|
||||
ePicType picType;
|
||||
bool clickable, drawFramed, drawScaled;
|
||||
bool drawFramed, drawScaled;
|
||||
void drawPresetTer(short num, rectangle to_rect);
|
||||
void drawPresetTerAnim(short num, rectangle to_rect);
|
||||
void drawPresetMonstSm(short num, rectangle to_rect);
|
||||
@@ -131,7 +136,6 @@ private:
|
||||
void drawPartyItem(short num, rectangle to_rect);
|
||||
void drawPartyPc(short num, rectangle to_rect);
|
||||
static std::map<ePicType,void(cPict::*)(short,rectangle)>& drawPict();
|
||||
click_callback_t onClick;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,14 @@ bool cScrollbar::isClickable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cScrollbar::isFocusable(){
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cScrollbar::isScrollable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
void cScrollbar::setPosition(long newPos) {
|
||||
pos = minmax(0,max,newPos);
|
||||
}
|
||||
@@ -75,20 +83,6 @@ eScrollStyle cScrollbar::getStyle() {
|
||||
return style;
|
||||
}
|
||||
|
||||
void cScrollbar::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) {
|
||||
onClick = f;
|
||||
}
|
||||
|
||||
void cScrollbar::attachFocusHandler(focus_callback_t) throw(xHandlerNotSupported) {
|
||||
throw xHandlerNotSupported(true);
|
||||
}
|
||||
|
||||
bool cScrollbar::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods) {
|
||||
// TODO: Implement detection of scrolling stuff, maybe even dragging the thumb
|
||||
if(onClick != nullptr) return onClick(me,id,mods);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cScrollbar::handleClick(location where) {
|
||||
if(max == 0) return false;
|
||||
sf::Event e;
|
||||
|
||||
@@ -44,7 +44,6 @@ class cScrollbar : public cControl {
|
||||
} pressedPart;
|
||||
eScrollStyle style = SCROLL_WHITE;
|
||||
bool vert = true;
|
||||
click_callback_t onClick;
|
||||
static sf::Texture scroll_gw[NUM_STYLES];
|
||||
static const rectangle up_rect[NUM_STYLES][4], down_rect[NUM_STYLES][4], bar_rect[NUM_STYLES][4], thumb_rect[NUM_STYLES][4];
|
||||
void draw_vertical(), draw_horizontal();
|
||||
@@ -58,9 +57,6 @@ public:
|
||||
/// Create a new scrollbar.
|
||||
/// @param parent The parent dialog.
|
||||
explicit cScrollbar(cDialog& parent);
|
||||
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
bool handleClick(location where);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
@@ -69,6 +65,8 @@ public:
|
||||
storage_t store();
|
||||
void restore(storage_t to);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
/// Get the scrollbar thumb's current position.
|
||||
/// @return The current position.
|
||||
long getPosition();
|
||||
@@ -118,6 +116,12 @@ public:
|
||||
/// @param newStyle The new style.
|
||||
void setStyle(eScrollStyle newStyle);
|
||||
void draw();
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK, EVT_SCROLL};
|
||||
}
|
||||
cScrollbar& operator=(cScrollbar& other) = delete;
|
||||
cScrollbar(cScrollbar& other) = delete;
|
||||
};
|
||||
|
||||
@@ -17,27 +17,25 @@ cScrollPane::cScrollPane(cDialog& parent) : cContainer(CTRL_PANE, parent), scrol
|
||||
recalcRect();
|
||||
}
|
||||
|
||||
void cScrollPane::attachClickHandler(click_callback_t) throw(xHandlerNotSupported) {
|
||||
throw xHandlerNotSupported(false);
|
||||
}
|
||||
|
||||
void cScrollPane::attachFocusHandler(focus_callback_t) throw(xHandlerNotSupported) {
|
||||
throw xHandlerNotSupported(true);
|
||||
}
|
||||
|
||||
bool cScrollPane::triggerClickHandler(cDialog&, std::string, eKeyMod) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cScrollPane::handleClick(location where) {
|
||||
if(scroll.getBounds().contains(where))
|
||||
return scroll.handleClick(where);
|
||||
where.y += scroll.getPosition();
|
||||
for(auto& ctrl : contents) {
|
||||
if(ctrl.second->isClickable() && ctrl.second->getBounds().contains(where))
|
||||
return ctrl.second->handleClick(where);
|
||||
}
|
||||
return false;
|
||||
return cContainer::handleClick(where);
|
||||
}
|
||||
|
||||
bool cContainer::handleClick(location where) {
|
||||
std::string which_clicked;
|
||||
bool success = false;
|
||||
forEach([&](std::string id, cControl& ctrl) {
|
||||
if(ctrl.isClickable() && ctrl.getBounds().contains(where)) {
|
||||
success = ctrl.handleClick(where);
|
||||
which_clicked = id;
|
||||
}
|
||||
});
|
||||
if(!which_clicked.empty())
|
||||
clicking = which_clicked;
|
||||
return success;
|
||||
}
|
||||
|
||||
void cScrollPane::recalcRect() {
|
||||
@@ -114,6 +112,14 @@ bool cScrollPane::isClickable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cScrollPane::isFocusable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cScrollPane::isScrollable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
long cScrollPane::getPosition() {
|
||||
return scroll.getPosition();
|
||||
}
|
||||
@@ -166,6 +172,11 @@ void cScrollPane::draw() {
|
||||
drawFrame(4, frameStyle);
|
||||
}
|
||||
|
||||
void cScrollPane::forEach(std::function<void(std::string,cControl&)> callback) {
|
||||
for(auto ctrl : contents)
|
||||
callback(ctrl.first, *ctrl.second);
|
||||
}
|
||||
|
||||
std::string cScrollPane::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
|
||||
@@ -24,9 +24,6 @@ public:
|
||||
/// Create a new scroll pane
|
||||
explicit cScrollPane(cDialog& parent);
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
bool handleClick(location where);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
@@ -37,6 +34,8 @@ public:
|
||||
storage_t store();
|
||||
void restore(storage_t to);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
/// Add a new control to this pane.
|
||||
/// @param ctrl A pointer to the control, which should already be constructed.
|
||||
/// @param key A key to be used to look up the control later.
|
||||
@@ -60,6 +59,13 @@ public:
|
||||
/// @param newStyle The new style.
|
||||
void setStyle(eScrollStyle newStyle);
|
||||
void draw();
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK, EVT_SCROLL, EVT_FOCUS, EVT_DEFOCUS};
|
||||
}
|
||||
void forEach(std::function<void(std::string,cControl&)> callback) override;
|
||||
cScrollPane& operator=(cScrollPane& other) = delete;
|
||||
cScrollPane(cScrollPane& other) = delete;
|
||||
};
|
||||
|
||||
@@ -22,39 +22,13 @@ cControl& cStack::getChild(std::string id) {
|
||||
return *controls[id];
|
||||
}
|
||||
|
||||
void cStack::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) {
|
||||
onClick = f;
|
||||
}
|
||||
|
||||
void cStack::attachFocusHandler(focus_callback_t) throw(xHandlerNotSupported) {
|
||||
throw xHandlerNotSupported(true);
|
||||
}
|
||||
|
||||
bool cStack::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods) {
|
||||
void cContainer::callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) {
|
||||
std::string which_clicked = clicking;
|
||||
clicking = "";
|
||||
|
||||
if(onClick) onClick(me, id, mods);
|
||||
return controls[which_clicked]->triggerClickHandler(me, which_clicked, mods);
|
||||
}
|
||||
|
||||
bool cStack::handleClick(location where) {
|
||||
std::string which_clicked;
|
||||
auto iter = controls.begin();
|
||||
while(iter != controls.end()){
|
||||
if(iter->second->isVisible() && where.in(iter->second->getBounds())){
|
||||
if(iter->second->handleClick(where)) {
|
||||
which_clicked = iter->first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
if(which_clicked == "") return false;
|
||||
|
||||
clicking = which_clicked;
|
||||
return true;
|
||||
if(!which_clicked.empty())
|
||||
getChild(which_clicked).triggerClickHandler(me, which_clicked, mods);
|
||||
}
|
||||
|
||||
void cStack::setFormat(eFormat prop, short val) throw(xUnsupportedProp) {
|
||||
@@ -82,6 +56,14 @@ bool cStack::isClickable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cStack::isFocusable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cStack::isScrollable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void cStack::draw() {
|
||||
if(!isVisible()) return;
|
||||
for(auto& p : controls) {
|
||||
@@ -167,6 +149,11 @@ void cStack::fillTabOrder(std::vector<int>& specificTabs, std::vector<int>& reve
|
||||
|
||||
cStack::cStack(cDialog& parent) : cContainer(CTRL_STACK, parent), curPage(0), nPages(0) {}
|
||||
|
||||
void cStack::forEach(std::function<void(std::string,cControl&)> callback) {
|
||||
for(auto ctrl : controls)
|
||||
callback(ctrl.first, *ctrl.second);
|
||||
}
|
||||
|
||||
std::string cStack::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
|
||||
@@ -36,19 +36,16 @@ class cStack : public cContainer {
|
||||
std::string clicking;
|
||||
std::vector<std::map<std::string,storage_t>> storage;
|
||||
std::map<std::string,cControl*> controls;
|
||||
click_callback_t onClick;
|
||||
bool drawFramed;
|
||||
bool drawFramed = false;
|
||||
public:
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods);
|
||||
bool handleClick(location where);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
void setColour(sf::Color clr) throw(xUnsupportedProp);
|
||||
sf::Color getColour() throw(xUnsupportedProp);
|
||||
bool isClickable();
|
||||
bool isFocusable();
|
||||
bool isScrollable();
|
||||
void draw();
|
||||
bool hasChild(std::string id);
|
||||
cControl& getChild(std::string id);
|
||||
@@ -79,6 +76,13 @@ public:
|
||||
/// Create a new stack
|
||||
/// @param parent The parent dialog.
|
||||
cStack(cDialog& parent);
|
||||
/// @copydoc cControl::getSupportedHandlers
|
||||
///
|
||||
/// @todo Document possible handlers
|
||||
const std::set<eDlogEvt> getSupportedHandlers() const {
|
||||
return {EVT_CLICK, EVT_FOCUS, EVT_DEFOCUS};
|
||||
}
|
||||
void forEach(std::function<void(std::string,cControl&)> callback) override;
|
||||
cStack& operator=(cStack& other) = delete;
|
||||
cStack(cStack& other) = delete;
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ are required. Some controls may ignore the `width` and `height`
|
||||
attributes.
|
||||
* `def-key` - Specifies the default keyboard shortcut for the
|
||||
control. See **Keyboard Shortcuts** below for more information on the
|
||||
format of these attributes.
|
||||
format of this attribute.
|
||||
* `font`, `size`, `color`, `colour` - Specifies text attributes of the
|
||||
control. See **Text Formatting** below for details on accepted values.
|
||||
* `name` - Give the control a unique identifier which you can use to
|
||||
@@ -72,9 +72,6 @@ The `<text>` tag accepts the following attributes:
|
||||
|
||||
* `framed` - See **Common Attributes** above. Defaults to `false`.
|
||||
* `outline` - See **Common Attributes** above.
|
||||
* `clickable` - Specifies that the text is clickable. This attribute is
|
||||
useless, as clickability is determined solely by having a click handler
|
||||
set in the code.
|
||||
* `fromlist`, `font`, `size`, `color`, `colour`, `def-key` -
|
||||
See **Common Attributes** above.
|
||||
|
||||
@@ -106,19 +103,20 @@ The possible values for the `type` attribute are:
|
||||
* `right` - A normal-sized 63x23 button with a right-pointing arrow.
|
||||
* `up` - A normal-sized 63x23 button with an up-pointing arrow.
|
||||
* `down` - A normal-sized 63x23 button with a down-pointing arrow.
|
||||
* `tiny` - A tiny 14x10 button, same size as an LED.
|
||||
* `tiny` - A tiny 14x10 button, same size as an LED and with the same
|
||||
label behaviour.
|
||||
* `done` - A normal-sized 63x23 button with "Done" on it.
|
||||
* `tall` - A tall 63x40 button.
|
||||
* `trait` - A tall 63x40 button with "Race Good/Bad Traits" on it.
|
||||
* `push` - A round red 30x30 push button.
|
||||
|
||||
(Naturally, they correspond perfectly with the values of the eBtnType
|
||||
(Naturally, they correspond perfectly with the values of the @ref eBtnType
|
||||
enumeration.)
|
||||
|
||||
The `<led>` tag
|
||||
---------------
|
||||
|
||||
The `<led>` tag descripts an LED button. It can contain label text,
|
||||
The `<led>` tag describes an LED button. It can contain label text,
|
||||
which is drawn to the right of the button graphic. This differs from
|
||||
normal practice in the original Blades of Exile dialog engine, where LED
|
||||
labels were typically left-aligned to the _left_ of their associated
|
||||
@@ -158,9 +156,6 @@ The `<pict>` tag accepts the following attributes:
|
||||
|
||||
* `type` - Specifies the type of graphic. This attribute is required.
|
||||
* `num` - Specifies the graphic number. This attribute is required.
|
||||
* `clickable` - Specifies that the picture is clickable. This attribute
|
||||
is useless, as clickability is determined solely by having a click
|
||||
handler set in the code.
|
||||
* `custom` - Specifies whether the picture is custom or preset. Can be
|
||||
either `true` or `false`; defaults to `false`.
|
||||
* `framed` - See **Common Attributes** above. Defaults to `true`.
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/// Resources include sounds, images, fonts, and cursors.
|
||||
///
|
||||
/// To implement a new resource type, all you have to do is specialize
|
||||
/// @a ResMgr::resLoader::operator() and declare @a ResMgr::resLoader::file_ext
|
||||
/// @ref ResMgr::resLoader::operator()() and declare @ref ResMgr::resLoader::file_ext
|
||||
/// for the desired resource type. The operator() receives the
|
||||
/// full file path with the extension already applied.
|
||||
namespace ResMgr {
|
||||
|
||||
Reference in New Issue
Block a user