From f14c99f14b6df1e924d60ad602cb7bb06dc58f93 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Mon, 21 Dec 2020 17:16:15 -0500 Subject: [PATCH] Split out cContainer, cLed, and cLedGroup into their own files --- proj/vs2013/Common/Common.vcxproj | 9 +- proj/vs2013/Common/Common.vcxproj.filters | 27 +- proj/vs2017/Common/Common.vcxproj | 9 +- proj/vs2017/Common/Common.vcxproj.filters | 27 +- proj/xc4/BoE.xcodeproj/project.pbxproj | 34 +- src/dialogxml/SConscript | 2 +- src/dialogxml/dialogs/3choice.hpp | 2 +- src/dialogxml/dialogs/dialog.cpp | 37 +- src/dialogxml/dialogs/dialog.hpp | 11 +- src/dialogxml/dialogs/dlogevt.hpp | 2 +- src/dialogxml/dialogs/pictchoice.hpp | 2 +- src/dialogxml/dialogs/strchoice.hpp | 2 +- src/dialogxml/keycodes.cpp | 116 ++++++ .../{dialogs/dialog.keys.hpp => keycodes.hpp} | 0 src/dialogxml/widgets/button.cpp | 382 +----------------- src/dialogxml/widgets/button.hpp | 160 -------- src/dialogxml/widgets/container.cpp | 74 ++++ src/dialogxml/widgets/container.hpp | 53 +++ src/dialogxml/widgets/control.cpp | 2 + src/dialogxml/widgets/control.hpp | 58 +-- src/dialogxml/widgets/led.cpp | 154 +++++++ src/dialogxml/widgets/led.hpp | 67 +++ src/dialogxml/widgets/ledgroup.cpp | 247 +++++++++++ src/dialogxml/widgets/ledgroup.hpp | 116 ++++++ src/dialogxml/widgets/scrollbar.cpp | 1 + src/dialogxml/widgets/scrollpane.cpp | 15 +- src/dialogxml/widgets/scrollpane.hpp | 1 + src/dialogxml/widgets/stack.cpp | 10 +- src/dialogxml/widgets/stack.hpp | 2 +- src/game/boe.dlgutil.cpp | 1 + src/game/boe.graphics.cpp | 1 + src/game/boe.newgraph.cpp | 2 + src/pcedit/pc.editors.cpp | 1 + src/scenedit/scen.townout.cpp | 1 + src/view_dialogs.cpp | 1 + 35 files changed, 963 insertions(+), 666 deletions(-) create mode 100644 src/dialogxml/keycodes.cpp rename src/dialogxml/{dialogs/dialog.keys.hpp => keycodes.hpp} (100%) create mode 100644 src/dialogxml/widgets/container.cpp create mode 100644 src/dialogxml/widgets/container.hpp create mode 100644 src/dialogxml/widgets/led.cpp create mode 100644 src/dialogxml/widgets/led.hpp create mode 100644 src/dialogxml/widgets/ledgroup.cpp create mode 100644 src/dialogxml/widgets/ledgroup.hpp diff --git a/proj/vs2013/Common/Common.vcxproj b/proj/vs2013/Common/Common.vcxproj index 8a5e5438..66df272a 100644 --- a/proj/vs2013/Common/Common.vcxproj +++ b/proj/vs2013/Common/Common.vcxproj @@ -192,6 +192,7 @@ + @@ -200,8 +201,11 @@ + + + @@ -267,17 +271,20 @@ + - + + + diff --git a/proj/vs2013/Common/Common.vcxproj.filters b/proj/vs2013/Common/Common.vcxproj.filters index f9e64762..9667b97e 100644 --- a/proj/vs2013/Common/Common.vcxproj.filters +++ b/proj/vs2013/Common/Common.vcxproj.filters @@ -731,6 +731,9 @@ FileIO\ResMgr + + DialogXML + DialogXML\Widgets @@ -746,12 +749,21 @@ DialogXML\Widgets + + DialogXML\Widgets + + + DialogXML\Widgets + DialogXML\Widgets DialogXML\Widgets + + DialogXML\Widgets + DialogXML\Widgets @@ -947,12 +959,21 @@ DialogXML\Widgets + + DialogXML\Widgets + + + DialogXML\Widgets + DialogXML\Widgets DialogXML\Widgets + + DialogXML\Widgets + DialogXML\Widgets @@ -968,15 +989,15 @@ DialogXML\Dialogs - - DialogXML\Dialogs - DialogXML\Dialogs DialogXML\Dialogs + + DialogXML + Tools diff --git a/proj/vs2017/Common/Common.vcxproj b/proj/vs2017/Common/Common.vcxproj index 265a9727..a94106f8 100644 --- a/proj/vs2017/Common/Common.vcxproj +++ b/proj/vs2017/Common/Common.vcxproj @@ -326,6 +326,7 @@ + @@ -334,8 +335,11 @@ + + + @@ -396,17 +400,20 @@ + - + + + diff --git a/proj/vs2017/Common/Common.vcxproj.filters b/proj/vs2017/Common/Common.vcxproj.filters index baacd966..18768489 100644 --- a/proj/vs2017/Common/Common.vcxproj.filters +++ b/proj/vs2017/Common/Common.vcxproj.filters @@ -721,6 +721,9 @@ + + DialogXML + DialogXML\Dialogs @@ -745,12 +748,21 @@ DialogXML\Widgets + + DialogXML\Widgets + DialogXML\Widgets DialogXML\Widgets + + DialogXML\Widgets + + + DialogXML\Widgets + DialogXML\Widgets @@ -935,6 +947,9 @@ + + DialogXML + DialogXML\Dialogs @@ -944,9 +959,6 @@ DialogXML\Dialogs - - DialogXML\Dialogs - DialogXML\Dialogs @@ -962,12 +974,21 @@ DialogXML\Widgets + + DialogXML\Widgets + DialogXML\Widgets DialogXML\Widgets + + DialogXML\Widgets + + + DialogXML\Widgets + DialogXML\Widgets diff --git a/proj/xc4/BoE.xcodeproj/project.pbxproj b/proj/xc4/BoE.xcodeproj/project.pbxproj index d2f7ee04..c15da78d 100755 --- a/proj/xc4/BoE.xcodeproj/project.pbxproj +++ b/proj/xc4/BoE.xcodeproj/project.pbxproj @@ -79,6 +79,14 @@ 91279BB80F9D03B7007B0D52 /* boegraphics.icns in Resources */ = {isa = PBXBuildFile; fileRef = 91279BB50F9D03B7007B0D52 /* boegraphics.icns */; }; 912DFE8F18E2872400B00D75 /* boe.menus.mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 912DFE8E18E2872300B00D75 /* boe.menus.mac.mm */; }; 913D6C050FC57A8E00E12527 /* boeresources.icns in Resources */ = {isa = PBXBuildFile; fileRef = 913D6C040FC57A8E00E12527 /* boeresources.icns */; }; + 9149924B25913E3F00B5BE97 /* container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9149924525913E3F00B5BE97 /* container.cpp */; }; + 9149924C25913E3F00B5BE97 /* container.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9149924625913E3F00B5BE97 /* container.hpp */; }; + 9149924D25913E3F00B5BE97 /* led.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9149924725913E3F00B5BE97 /* led.cpp */; }; + 9149924E25913E3F00B5BE97 /* led.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9149924825913E3F00B5BE97 /* led.hpp */; }; + 9149924F25913E3F00B5BE97 /* ledgroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9149924925913E3F00B5BE97 /* ledgroup.cpp */; }; + 9149925025913E3F00B5BE97 /* ledgroup.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9149924A25913E3F00B5BE97 /* ledgroup.hpp */; }; + 91499253259140FF00B5BE97 /* keycodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91499251259140FF00B5BE97 /* keycodes.cpp */; }; + 91499254259140FF00B5BE97 /* keycodes.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 91499252259140FF00B5BE97 /* keycodes.hpp */; }; 914B2AA318E7E507007B6799 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA118E7E500007B6799 /* Cocoa.framework */; }; 914B2AA418E7E509007B6799 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA118E7E500007B6799 /* Cocoa.framework */; }; 914B2AA518E7E50A007B6799 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA118E7E500007B6799 /* Cocoa.framework */; }; @@ -607,6 +615,14 @@ 914698FD1A747BED00F20F5E /* creature.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = creature.hpp; sourceTree = ""; }; 914698FE1A747C4500F20F5E /* creature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = creature.cpp; sourceTree = ""; }; 914701A918F64A85008A6DC9 /* dialog.xsd */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = dialog.xsd; sourceTree = ""; }; + 9149924525913E3F00B5BE97 /* container.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = container.cpp; sourceTree = ""; }; + 9149924625913E3F00B5BE97 /* container.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = container.hpp; sourceTree = ""; }; + 9149924725913E3F00B5BE97 /* led.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = led.cpp; sourceTree = ""; }; + 9149924825913E3F00B5BE97 /* led.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = led.hpp; sourceTree = ""; }; + 9149924925913E3F00B5BE97 /* ledgroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ledgroup.cpp; sourceTree = ""; }; + 9149924A25913E3F00B5BE97 /* ledgroup.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ledgroup.hpp; sourceTree = ""; }; + 91499251259140FF00B5BE97 /* keycodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keycodes.cpp; sourceTree = ""; }; + 91499252259140FF00B5BE97 /* keycodes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = keycodes.hpp; sourceTree = ""; }; 914B2AA118E7E500007B6799 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 914B2AA218E7E500007B6799 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; 914B2BB518E892AA007B6799 /* dialog-converting.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "dialog-converting.txt"; sourceTree = ""; }; @@ -660,7 +676,6 @@ 9185BDA61EA055180027C346 /* res_font.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = res_font.hpp; sourceTree = ""; }; 9185BDA71EA055180027C346 /* res_sound.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = res_sound.hpp; sourceTree = ""; }; 9185BDA81EA055180027C346 /* res_strings.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = res_strings.hpp; sourceTree = ""; }; - 918D59A718EA513900735B66 /* dialog.keys.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = dialog.keys.hpp; sourceTree = ""; }; 919086DF1A65C8E30071F7A0 /* tinyprint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyprint.cpp; sourceTree = ""; }; 919086E11A65D3250071F7A0 /* tinyprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinyprint.h; sourceTree = ""; }; 919145FB18E3A32F005CF3A4 /* boe.appleevents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = boe.appleevents.mm; sourceTree = ""; }; @@ -956,6 +971,8 @@ 910BBA130FB8BE66001E34EA /* dialogxml */ = { isa = PBXGroup; children = ( + 91499251259140FF00B5BE97 /* keycodes.cpp */, + 91499252259140FF00B5BE97 /* keycodes.hpp */, 910BBA140FB8BE7D001E34EA /* widgets */, 910BBA150FB8BE88001E34EA /* dialogs */, ); @@ -968,16 +985,22 @@ children = ( 91A32BD10FDB797B00C4E957 /* basicbtns.cpp */, 910BBA890FB8EC57001E34EA /* button.cpp */, + 9149924525913E3F00B5BE97 /* container.cpp */, 910BBA3C0FB8DA8E001E34EA /* control.cpp */, 910BBAB50FB91A26001E34EA /* field.cpp */, + 9149924725913E3F00B5BE97 /* led.cpp */, + 9149924925913E3F00B5BE97 /* ledgroup.cpp */, 910BBAB90FB91ADB001E34EA /* message.cpp */, 910BBAA90FB8F733001E34EA /* pict.cpp */, 9191460018E63D8E005CF3A4 /* scrollbar.cpp */, 919B13A81BBE2B54009905A4 /* scrollpane.cpp */, 9179A4641A48681800FEF872 /* stack.cpp */, 910BBA880FB8EC57001E34EA /* button.hpp */, + 9149924625913E3F00B5BE97 /* container.hpp */, 910BBA3B0FB8DA8E001E34EA /* control.hpp */, 910BBAB40FB91A26001E34EA /* field.hpp */, + 9149924825913E3F00B5BE97 /* led.hpp */, + 9149924A25913E3F00B5BE97 /* ledgroup.hpp */, 910BBAB80FB91ADB001E34EA /* message.hpp */, 910BBAA80FB8F733001E34EA /* pict.hpp */, 913FB40A1A5C90840067B9D2 /* pictypes.hpp */, @@ -1000,7 +1023,6 @@ 91E128F21BC2077600C8BE1D /* 3choice.hpp */, 91E128F31BC2077700C8BE1D /* choicedlog.hpp */, 910BBA170FB8BECA001E34EA /* dialog.hpp */, - 918D59A718EA513900735B66 /* dialog.keys.hpp */, 915AF9E91BC04171008AEF49 /* dlogevt.hpp */, 91E128F41BC2077700C8BE1D /* pictchoice.hpp */, 91E128F51BC2077700C8BE1D /* strchoice.hpp */, @@ -1561,6 +1583,10 @@ buildActionMask = 2147483647; files = ( 91F3205123E65EA3009650AF /* framerate_limiter.hpp in Headers */, + 9149924C25913E3F00B5BE97 /* container.hpp in Headers */, + 9149924E25913E3F00B5BE97 /* led.hpp in Headers */, + 9149925025913E3F00B5BE97 /* ledgroup.hpp in Headers */, + 91499254259140FF00B5BE97 /* keycodes.hpp in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1963,6 +1989,10 @@ 91EC1F0823DDFF9D00271891 /* res_strings.cpp in Sources */, 91F3205023E65EA3009650AF /* framerate_limiter.cpp in Sources */, 91FE0E3823F084B70084CA6B /* drawable_manager.cpp in Sources */, + 9149924B25913E3F00B5BE97 /* container.cpp in Sources */, + 9149924D25913E3F00B5BE97 /* led.cpp in Sources */, + 9149924F25913E3F00B5BE97 /* ledgroup.cpp in Sources */, + 91499253259140FF00B5BE97 /* keycodes.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/dialogxml/SConscript b/src/dialogxml/SConscript index bd933853..7ef3c7c4 100644 --- a/src/dialogxml/SConscript +++ b/src/dialogxml/SConscript @@ -4,6 +4,6 @@ Import("env") env = env.Clone() if 'msvc' not in env["TOOLS"]: env.Append(CXXFLAGS="-fpermissive") -dlog_util = env.StaticLibrary("#build/lib/dlogutil", Glob("dialogs/*.cpp") + Glob("widgets/*.cpp") + Glob("../fileio/xml-parser/*.cpp")) +dlog_util = env.StaticLibrary("#build/lib/dlogutil", Glob("*.cpp") + Glob("dialogs/*.cpp") + Glob("widgets/*.cpp") + Glob("../fileio/xml-parser/*.cpp")) Return("dlog_util") diff --git a/src/dialogxml/dialogs/3choice.hpp b/src/dialogxml/dialogs/3choice.hpp index e0191744..75d2e4fc 100644 --- a/src/dialogxml/dialogs/3choice.hpp +++ b/src/dialogxml/dialogs/3choice.hpp @@ -14,7 +14,7 @@ #include #include -#include "dialog.keys.hpp" +#include "keycodes.hpp" #include "choicedlog.hpp" #include "button.hpp" #include "pictypes.hpp" diff --git a/src/dialogxml/dialogs/dialog.cpp b/src/dialogxml/dialogs/dialog.cpp index 6f3f80dd..aa115d5f 100644 --- a/src/dialogxml/dialogs/dialog.cpp +++ b/src/dialogxml/dialogs/dialog.cpp @@ -14,6 +14,7 @@ #include "pict.hpp" #include "button.hpp" #include "field.hpp" +#include "ledgroup.hpp" #include "message.hpp" #include "scrollbar.hpp" #include "scrollpane.hpp" @@ -417,42 +418,6 @@ void cDialog::loadFromFile(std::string path){ } } -// TODO: Move to a dedicated container.cpp? -bool cContainer::parseChildControl(ticpp::Element& elem, std::map& controls, std::string& id) { - std::string tag = elem.Value(); - if(tag == "field") { - auto field = parent->parse(elem); - controls.insert(field); - parent->tabOrder.push_back(field); - id = field.first; - } else if(tag == "text") { - auto text = parent->parse(elem); - controls.insert(text); - id = text.first; - } else if(tag == "pict") { - auto pict = parent->parse(elem); - controls.insert(pict); - id = pict.first; - } else if(tag == "slider") { - auto slide = parent->parse(elem); - controls.insert(slide); - id = slide.first; - } else if(tag == "button") { - auto button = parent->parse(elem); - controls.insert(button); - id = button.first; - } else if(tag == "led") { - auto led = parent->parse(elem); - controls.insert(led); - id = led.first; - } else if(tag == "group") { - auto group = parent->parse(elem); - controls.insert(group); - id = group.first; - } else return false; - return true; -} - void cDialog::recalcRect(){ bool haveRel = false; for(ctrlIter iter = controls.begin(); iter != controls.end(); iter++) { diff --git a/src/dialogxml/dialogs/dialog.hpp b/src/dialogxml/dialogs/dialog.hpp index 2b26dc59..d789433f 100644 --- a/src/dialogxml/dialogs/dialog.hpp +++ b/src/dialogxml/dialogs/dialog.hpp @@ -21,7 +21,7 @@ #include #include "ticpp.h" -#include "dialog.keys.hpp" +#include "keycodes.hpp" #include "dlogevt.hpp" #include "location.hpp" #include @@ -320,4 +320,13 @@ public: const char* what() const throw(); }; +//// This needs cControl to be complete. +///// @note You need to include control.hpp to use this. +//template void cDialog::attachEventHandlers(typename event_fcn::type handler, const std::vector& controls) { +// cDialog& me = *this; +// for(std::string control : controls) { +// me[control].attachEventHandler(handler); +// } +//} + #endif diff --git a/src/dialogxml/dialogs/dlogevt.hpp b/src/dialogxml/dialogs/dlogevt.hpp index c991bc93..dc56f22f 100644 --- a/src/dialogxml/dialogs/dlogevt.hpp +++ b/src/dialogxml/dialogs/dlogevt.hpp @@ -12,7 +12,7 @@ #include #include #include -#include "dialog.keys.hpp" +#include "keycodes.hpp" /// Represents an event that can occur in a dialog. enum eDlogEvt { diff --git a/src/dialogxml/dialogs/pictchoice.hpp b/src/dialogxml/dialogs/pictchoice.hpp index e9567cd8..8c0a0566 100644 --- a/src/dialogxml/dialogs/pictchoice.hpp +++ b/src/dialogxml/dialogs/pictchoice.hpp @@ -14,7 +14,7 @@ #include #include "dialog.hpp" -#include "button.hpp" +#include "ledgroup.hpp" #include "pictypes.hpp" /// A dialog that presents a list of icons with LEDs and allows you to choose one. diff --git a/src/dialogxml/dialogs/strchoice.hpp b/src/dialogxml/dialogs/strchoice.hpp index 143d8e62..cd9102f2 100644 --- a/src/dialogxml/dialogs/strchoice.hpp +++ b/src/dialogxml/dialogs/strchoice.hpp @@ -13,7 +13,7 @@ #include #include #include "dialog.hpp" -#include "button.hpp" +#include "ledgroup.hpp" /// A dialog that presents a list of strings with LEDs and allows you to choose one. /// The list may span several pages. diff --git a/src/dialogxml/keycodes.cpp b/src/dialogxml/keycodes.cpp new file mode 100644 index 00000000..df3578de --- /dev/null +++ b/src/dialogxml/keycodes.cpp @@ -0,0 +1,116 @@ +/* + * control.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include "keycodes.hpp" +//#include +//#include "dialog.hpp" +//#include "sounds.hpp" +//#include "button.hpp" +//#include "render_shapes.hpp" +//#include "res_image.hpp" +//#include "mathutil.hpp" +//#include "prefs.hpp" +//#include "cursors.hpp" + +eKeyMod operator + (eKeyMod lhs, eKeyMod rhs){ + if(lhs == rhs) return lhs; + else if(lhs == mod_none) return rhs; + else if(lhs == mod_alt){ + if(rhs == mod_shift || rhs == mod_altshift) return mod_altshift; + else if(rhs == mod_ctrl || rhs == mod_altctrl) return mod_altctrl; + else if(rhs == mod_shiftctrl || rhs == mod_all) return mod_all; + else return mod_alt; + }else if(lhs == mod_shift){ + if(rhs == mod_alt || rhs == mod_altshift) return mod_altshift; + else if(rhs == mod_ctrl || rhs == mod_shiftctrl) return mod_shiftctrl; + else if(rhs == mod_altctrl || rhs == mod_all) return mod_all; + else return mod_shift; + }else if(lhs == mod_ctrl){ + if(rhs == mod_alt || rhs == mod_altctrl) return mod_altctrl; + else if(rhs == mod_shift || rhs == mod_shiftctrl) return mod_shiftctrl; + else if(rhs == mod_altshift || rhs == mod_all) return mod_all; + else return mod_ctrl; + }else return rhs + lhs; +} + +eKeyMod operator - (eKeyMod lhs, eKeyMod rhs){ + if(lhs == rhs || lhs == mod_none || rhs == mod_all) return mod_none; + else if(rhs == mod_none) return lhs; + else if(lhs == mod_all){ + if(rhs == mod_alt) return mod_shiftctrl; + else if(rhs == mod_shift) return mod_altctrl; + else if(rhs == mod_ctrl) return mod_altshift; + else if(rhs == mod_altshift) return mod_ctrl; + else if(rhs == mod_altctrl) return mod_shift; + else if(rhs == mod_shiftctrl) return mod_alt; + else return mod_all; + }else if(lhs == mod_shiftctrl){ + if(rhs == mod_shift || rhs == mod_altshift) return mod_ctrl; + else if(rhs == mod_ctrl || rhs == mod_altctrl) return mod_shift; + else return mod_shiftctrl; + }else if(lhs == mod_altctrl){ + if(rhs == mod_alt || rhs == mod_altshift) return mod_ctrl; + else if(rhs == mod_ctrl || rhs == mod_shiftctrl) return mod_alt; + else return mod_altctrl; + }else if(lhs == mod_altshift){ + if(rhs == mod_alt || rhs == mod_altctrl) return mod_shift; + else if(rhs == mod_shift || rhs == mod_shiftctrl) return mod_alt; + else return mod_altshift; + }else if(lhs == mod_alt && (rhs == mod_altshift || rhs == mod_altctrl)) + return mod_none; + else if(lhs == mod_shift && (rhs == mod_altshift || rhs == mod_shiftctrl)) + return mod_none; + else if(lhs == mod_ctrl && (rhs == mod_altctrl || rhs == mod_shiftctrl)) + return mod_none; + else return lhs; +} + +eKeyMod& operator += (eKeyMod&lhs, eKeyMod rhs){ + lhs = lhs + rhs; + return lhs; +} + +eKeyMod& operator -= (eKeyMod&lhs, eKeyMod rhs){ + lhs = lhs - rhs; + return lhs; +} + +bool operator== (cKey a, cKey b){ + if(a.spec != b.spec) return false; + if(a.mod != b.mod) return false; + return a.spec ? a.k == b.k : (a.c == 0 ? false : a.c == b.c); +} + +bool mod_contains(eKeyMod mods, eKeyMod mod) { + if((mods & mod) != 0) return true; + return false; +} + +unsigned char applyShift(unsigned char c){ + static const char afterShift[] = { + ' ', '!', '"', '#', '$', '%', '&', '"', '(', ')', '*', '+', '<', '_', '>', '?', + ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', ':', ':', '<', '+', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '^', '_', + '~', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', + }; + return afterShift[c - ' ']; +} + +unsigned char removeShift(unsigned char c){ + static const char afterUnShift[] = { + ' ', '1', '\'','3', '4', '5', '7', '\'','9', '0', '8', '=', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';', ';', ',', '=', '.', '/', + '2', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '6', '-', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\',']', '`', + }; + return afterUnShift[c - ' ']; +} diff --git a/src/dialogxml/dialogs/dialog.keys.hpp b/src/dialogxml/keycodes.hpp similarity index 100% rename from src/dialogxml/dialogs/dialog.keys.hpp rename to src/dialogxml/keycodes.hpp diff --git a/src/dialogxml/widgets/button.cpp b/src/dialogxml/widgets/button.cpp index b60d5c7a..6fa57429 100644 --- a/src/dialogxml/widgets/button.cpp +++ b/src/dialogxml/widgets/button.cpp @@ -8,16 +8,10 @@ */ #include "button.hpp" -#include -#include -#include -#include #include "dialog.hpp" #include "render_image.hpp" - -#include -#include +#include "render_text.hpp" #include "res_image.hpp" @@ -249,345 +243,8 @@ void cButton::init(){ btnRects[BTN_PUSH][1].offset(30,0); } -rectangle cLed::ledRects[3][2]; - -void cLed::init(){ - rectangle baseLed = {0,0,10,14}; - for(int i = 0; i < 3; i++) - for(int j = 0; j < 2; j++){ - ledRects[i][j] = baseLed; - ledRects[i][j].offset(i * 14, j * 10); - } -} - -cLed::cLed(cDialog& parent) : - cButton(parent,CTRL_LED), - state(led_off), - textFont(FONT_BOLD), - textSize(10) { - type = BTN_LED; - using namespace std::placeholders; - attachEventHandler(std::bind(&cLed::defaultClickHandler, this, _1, _2, _3)); -} - -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::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)){ - state = oldState; - } -} - -bool cLed::manageFormat(eFormat prop, bool set, boost::any* val) { - switch(prop) { - case TXT_FONT: - if(val) { - if(set) textFont = boost::any_cast(*val); - else *val = textFont; - } - break; - case TXT_SIZE: - if(val) { - if(set) textSize = boost::any_cast(*val); - else *val = textSize; - } - break; - case TXT_WRAP: - if(val) { - if(set) wrapLabel = boost::any_cast(*val); - else *val = wrapLabel; - } - break; - case TXT_COLOUR: - if(val) { - if(set) textClr = boost::any_cast(*val); - else *val = textClr; - } - break; - default: return false; - } - return true; -} - -void cLed::draw(){ - rectangle from_rect, to_rect; - - inWindow->setActive(); - - if(visible){ - TextStyle style; - style.pointSize = textSize; - style.lineHeight = textSize - 1; - style.font = textFont; - from_rect = ledRects[state][depressed]; - to_rect = frame; - to_rect.right = to_rect.left + 14; - to_rect.bottom = to_rect.top + 10; - rect_draw_some_item(*ResMgr::graphics.get(buttons[btnGW[BTN_LED]]),from_rect,*inWindow,to_rect); - style.colour = textClr; - to_rect.right = frame.right; - to_rect.left = frame.left + 18; // Possibly could be 20 - win_draw_string(*inWindow,to_rect,lbl,wrapLabel ? eTextMode::WRAP : eTextMode::LEFT_TOP,style); - } -} - -cControl::storage_t cLed::store() { - storage_t storage = cButton::store(); - storage["led-state"] = getState(); - return storage; -} - -void cLed::restore(storage_t to) { - cButton::restore(to); - if(to.find("led-state") != to.end()) - setState(boost::any_cast(to["led-state"])); - else setState(led_off); -} - -cLedGroup::cLedGroup(cDialog& parent) : - cContainer(CTRL_GROUP,parent), - fromList("none") {} - cButton::~cButton() {} -cLed::~cLed() {} - -cLedGroup::~cLedGroup(){ - ledIter iter = choices.begin(); - while(iter != choices.end()){ - delete iter->second; - iter++; - } -} - -void cLedGroup::recalcRect(){ - ledIter iter = choices.begin(); - frame = {INT_MAX, INT_MAX, 0, 0}; - while(iter != choices.end()){ - rectangle otherFrame = iter->second->getBounds(); - if(otherFrame.right > frame.right) - frame.right = otherFrame.right; - if(otherFrame.bottom > frame.bottom) - frame.bottom = otherFrame.bottom; - if(otherFrame.left < frame.left) - frame.left = otherFrame.left; - if(otherFrame.top < frame.top) - frame.top = otherFrame.top; - iter++; - } - frame.inset(-6,-6); -} - -void cLed::setState(eLedState to){ - state = to; -} - -eLedState cLed::getState(){ - return state; -} - -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; - } - 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); -} - -location cLed::getPreferredSize() { - return {ledRects[0][0].width(), ledRects[0][0].height()}; -} - -void cLedGroup::addChoice(cLed* ctrl, std::string key) { - choices[key] = ctrl; - if(ctrl->getState() != led_off) - setSelected(key); -} - -bool cLedGroup::handleClick(location where) { - std::string which_clicked; - ledIter iter = choices.begin(); - while(iter != choices.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; -} - -void cLedGroup::callHandler(event_fcn::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); - if(!curSelect.empty()) { - choices[curSelect]->setState(led_off); - if(!choices[curSelect]->triggerFocusHandler(me,curSelect,true)){ - choices[curSelect]->setState(led_red); - return; - } - } - choices[which_clicked]->setState(led_red); - if(!choices[which_clicked]->triggerFocusHandler(me,which_clicked,false)){ - if(!curSelect.empty()) - choices[curSelect]->setState(led_red); - choices[which_clicked]->setState(led_off); - return; - } - }else return; - - std::string savePrevSelect = prevSelect; - prevSelect = curSelect; - curSelect = which_clicked; - if(!triggerFocusHandler(me,id,false)) { - if(!curSelect.empty()) - choices[curSelect]->setState(led_red); - choices[which_clicked]->setState(led_off); - curSelect = prevSelect; - prevSelect = savePrevSelect; - return; - } - return; -} - -void cLedGroup::attachFocusHandler(std::function f) { - if(!f) { - attachEventHandler(nullptr); - return; - } - using namespace std::placeholders; - attachEventHandler([f](cDialog& me, std::string id) { - f(me, id, false); - }); -} - -void cLedGroup::disable(std::string /*id*/) { - // TODO: Implement this -} - -void cLedGroup::enable(std::string /*id*/) { - // TODO: Implement this -} - -void cLedGroup::show(std::string id){ - choices[id]->show(); -} - -void cLedGroup::hide(std::string id){ - choices[id]->hide(); -} - -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(); -} - -cLed& cLedGroup::getChild(std::string id){ - ledIter iter = choices.find(id); - if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup."); - return *(iter->second); -} - -void cLedGroup::setSelected(std::string id){ - if(id == "") { // deselect all - if(curSelect == "") return; - eLedState was = choices[curSelect]->getState(); - choices[curSelect]->setState(led_off); - if(choices[curSelect]->triggerFocusHandler(*parent,curSelect,true)) - curSelect = ""; - else - choices[curSelect]->setState(was); - return; - } - - ledIter iter = choices.find(id); - if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup."); - - if(curSelect == ""){ - if(iter->second->triggerFocusHandler(*parent,curSelect,false)){ - iter->second->setState(led_red); - curSelect = iter->first; - } - }else{ - eLedState a, b; - a = choices[curSelect]->getState(); - b = iter->second->getState(); - choices[curSelect]->setState(led_off); - iter->second->setState(led_red); - if(!choices[curSelect]->triggerFocusHandler(*parent,curSelect,true)){ - choices[curSelect]->setState(a); - iter->second->setState(b); - return; - } - if(!iter->second->triggerFocusHandler(*parent,curSelect,false)){ - choices[curSelect]->setState(a); - iter->second->setState(b); - return; - } - curSelect = iter->first; - } -} - -std::string cLedGroup::getSelected(){ - return curSelect; -} - -std::string cLedGroup::getPrevSelection(){ - return prevSelect; -} - -void cLedGroup::draw(){ - if(!visible) return; - ledIter iter = choices.begin(); - while(iter != choices.end()){ - iter->second->draw(); - iter++; - } - drawFrame(2, frameStyle); -} - void cButton::setBtnType(eBtnType newType){ if(type == BTN_LED || newType == BTN_LED) return; // can't change type type = newType; @@ -630,40 +287,3 @@ void cButton::setBtnType(eBtnType newType){ eBtnType cButton::getBtnType(){ return type; } - -cControl::storage_t cLedGroup::store() { - storage_t storage = cControl::store(); - storage["led-select"] = getSelected(); - return storage; -} - -void cLedGroup::restore(storage_t to) { - cControl::restore(to); - if(to.find("led-select") != to.end()) - setSelected(boost::any_cast(to["led-select"])); - else setSelected(""); -} - -void cLedGroup::forEach(std::function callback) { - for(auto ctrl : choices) - callback(ctrl.first, *ctrl.second); -} - -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(dynamic_cast(content)); - addChoice(led.second, led.first); - return true; - } else if(type == TiXmlNode::TEXT) { - return false; - } - return cContainer::parseContent(content, n, tagName, fname, text); -} - -void cLedGroup::validatePostParse(ticpp::Element& who, std::string fname, const std::set& attrs, const std::multiset& nodes) { - // Don't defer to super-class; groups are an abstract container that doesn't require a position. - //cControl::validatePostParse(who, fname, attrs, nodes); - frameStyle = FRM_NONE; -} diff --git a/src/dialogxml/widgets/button.hpp b/src/dialogxml/widgets/button.hpp index 7f73e317..11a95f24 100644 --- a/src/dialogxml/widgets/button.hpp +++ b/src/dialogxml/widgets/button.hpp @@ -9,16 +9,7 @@ #ifndef BUTTON_H #define BUTTON_H -/// @file -/// Button-related classes and types. - -#include - -#include -#include -#include #include "control.hpp" -#include "render_text.hpp" /// A button type. enum eBtnType { // w x h @@ -38,12 +29,6 @@ enum eBtnType { // w x h BTN_LED, /**< A tiny 14x10 LED button */// (PICT id 2018 / 2019 / 2020) }; -/// Represents the state of an LED button. -/// Generally, led_red is used to indicate a selected button. -/// Currently, led_green is only used by the spell selection dialog, -/// where led_red indicates the spell is available amd led_green indicates it is selected. -enum eLedState {led_green = 0, led_red, led_off}; - /// A clickable button control. class cButton : public cControl { @@ -102,149 +87,4 @@ protected: static std::string buttons[7]; }; -/// A LED button that can be either on or off. -/// Additionally, it supports two possible colours, red and green. -/// By default, it behaves like a checkbox, turning on or off when clicked. -/// This default behaviour always assumes a red LED. -class cLed : public cButton { -public: - /// @copydoc cDialog::init() - static void init(); - /// A handler that can be attached as a click handler to prevent the - /// default toggle-selected action of an LED. - /// @return true to indicate the event should continue. - static bool noAction(cDialog&,std::string,eKeyMod) {return true;} - 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; - location getPreferredSize() override; - storage_t store() override; - void restore(storage_t to) override; - /// Create a new LED button. - /// @param parent The parent dialog. - explicit cLed(cDialog& parent); - virtual ~cLed(); - /// Set the LED's current state,. - /// @param to The new state. - void setState(eLedState to); - /// Get the LED's current state. - /// @return The current state. - eLedState getState(); - void draw() override; - /// @copydoc cControl::getSupportedHandlers - /// - /// @todo Document possible handlers - const std::set getSupportedHandlers() const override { - 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::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; - static rectangle ledRects[3][2]; -}; - -/// A group of LED buttons that behave like radio buttons. -/// As with other standard LEDs, this always assumes red LEDs. -/// -/// When an LED in the group is clicked, the following sequence of events are fired: -/// -/// 1. The click handler of the clicked LED. -/// 2. The click handler of the LED group. -/// 3. The focus handler of the currently selected LED (if any), with the third parameter true. -/// 4. The focus handler of the clicked LED, with the third parameter false. -/// 5. The focus handler of the LED group, with the third parameter false. -/// -/// If at any stage a handler returns false, the entire sequence is aborted, and the -/// selection is not changed. A click within the group's space but not on any choice -/// triggers no events. -/// @note When the focus handlers of the individual LEDs are called, the selection has not yet been updated, -/// so calling the LED group's getSelected() method will still return the previous selection. -/// 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 { - std::map choices; - std::string fromList; - std::string curSelect, prevSelect; - std::string clicking; - void callHandler(event_fcn::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 f) 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& attrs, const std::multiset& 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. - /// - /// 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. - const std::set getSupportedHandlers() const override { - return {EVT_CLICK, EVT_FOCUS}; - } - storage_t store() override; - void restore(storage_t to) override; - /// Add a new LED to this group. - /// @param ctrl A pointer to the LED, which should already be constructed. - /// @param key A key to be used to look up the LED later. - /// @note This function is intended for internal use, which is why it takes a control pointer instead of a unique key. - void addChoice(cLed* ctrl, std::string key); - /// Disable one of the choices in this group. - /// @param id The unique key of the choice. - void disable(std::string id); - /// Enable one of the choices in this group. - /// @param id The unique key of the choice. - void enable(std::string id); - using cControl::show; - using cControl::hide; - /// Hide one of the choices in this group. - /// @param id The unique key of the choice. - void hide(std::string id); - /// Show one of the choices in this group. - /// @param id The unique key of the choice. - void show(std::string id); - /// Create a new LED group. - /// @param parent The parent dialog. - explicit cLedGroup(cDialog& parent); - bool isClickable() override; - bool isFocusable() override; - bool isScrollable() override; - bool handleClick(location where) override; - virtual ~cLedGroup(); - /// Get one of the LEDs in this group. - /// @param id The unique key of the choice. - /// @return A reference to the LED object. - /// @throw std::invalid_argument if the choice does not exist in the group. - cLed& getChild(std::string id) override; - bool hasChild(std::string id) override; - /// Set the currently selected LED in this group. - /// @param id The unique key of the choice. - /// @throw std::invalid_argument if the choice does not exist in the group. - void setSelected(std::string id); - /// Get the currently selected choice. - /// @return id The unique key of the choice. - std::string getSelected(); - /// Get the previously selected choice. - /// @return id The unique key of the choice. - /// @note This is intended for use by focus handlers. - /// - /// This refers to the element that was last selected before the selection changed to the current selection. - std::string getPrevSelection(); - /// Recalculate the LED group's bounding rect. - /// 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() override; - void forEach(std::function callback) override; - /// A convenience type for making an iterator into the choice map. - typedef std::map::iterator ledIter; - void draw() override; -}; #endif diff --git a/src/dialogxml/widgets/container.cpp b/src/dialogxml/widgets/container.cpp new file mode 100644 index 00000000..d261a1c5 --- /dev/null +++ b/src/dialogxml/widgets/container.cpp @@ -0,0 +1,74 @@ +/* + * container.cpp + * BoE + * + * Created by Celtic Minstrel on 2020-12-21. + * + */ + +#include "container.hpp" +#include "dialog.hpp" +#include "button.hpp" +#include "field.hpp" +#include "ledgroup.hpp" +#include "message.hpp" +#include "pict.hpp" +#include "scrollbar.hpp" + +bool cContainer::parseChildControl(ticpp::Element& elem, std::map& controls, std::string& id) { + std::string tag = elem.Value(); + if(tag == "field") { + auto field = parent->parse(elem); + controls.insert(field); + parent->tabOrder.push_back(field); + id = field.first; + } else if(tag == "text") { + auto text = parent->parse(elem); + controls.insert(text); + id = text.first; + } else if(tag == "pict") { + auto pict = parent->parse(elem); + controls.insert(pict); + id = pict.first; + } else if(tag == "slider") { + auto slide = parent->parse(elem); + controls.insert(slide); + id = slide.first; + } else if(tag == "button") { + auto button = parent->parse(elem); + controls.insert(button); + id = button.first; + } else if(tag == "led") { + auto led = parent->parse(elem); + controls.insert(led); + id = led.first; + } else if(tag == "group") { + auto group = parent->parse(elem); + controls.insert(group); + id = group.first; + } else return false; + return true; +} + +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 cContainer::callHandler(event_fcn::type onClick, cDialog& me, std::string id, eKeyMod mods) { + std::string which_clicked = clicking; + clicking = ""; + + if(onClick) onClick(me, id, mods); + if(!which_clicked.empty()) + getChild(which_clicked).triggerClickHandler(me, which_clicked, mods); +} diff --git a/src/dialogxml/widgets/container.hpp b/src/dialogxml/widgets/container.hpp new file mode 100644 index 00000000..9b5bc358 --- /dev/null +++ b/src/dialogxml/widgets/container.hpp @@ -0,0 +1,53 @@ +/* + * container.hpp + * BoE + * + * Created by Celtic Minstrel on 2020-12-21. + * + */ + +#ifndef BOE_DIALOG_CONTAINER_HPP +#define BOE_DIALOG_CONTAINER_HPP + +#include "control.hpp" + +/// A superclass to represent a control that contains other controls. +class cContainer : public cControl { + void callHandler(event_fcn::type onClick, cDialog& me, std::string id, eKeyMod mods) override; + std::string clicking; +protected: + /// Parses a child control. + /// @param elem The element defining the control. + /// @param controls The map into which the control will be inserted. + /// @param[out] The ID of the new control. + /// @return true if the element was a valid control, false otherwise. + bool parseChildControl(ticpp::Element& elem, std::map& controls, std::string& id); +public: + /// Create a new container control attached to an arbitrary window, rather than a dialog. + /// @param t The type of the control. + /// @param p The parent window. + cContainer(eControlType t, sf::RenderWindow& p) : cControl(t, p) {} + /// Create a new container control attached to a dialog. + /// @param t The type of the control. + /// @param p The parent dialog. + cContainer(eControlType t, cDialog& p) : cControl(t, p) {} + /// Check if a control exists with a given ID. + /// @param id The unique key of the control. + /// @return true if it exists. + virtual bool hasChild(std::string id) = 0; + /// Get a reference to a child control. + /// @param id The unique key of the control. + /// @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 callback) = 0; + /// @copydoc getChild() + cControl& operator[](std::string id) {return getChild(id);} + bool isContainer() override {return true;} + bool handleClick(location where) override; +}; + +#endif diff --git a/src/dialogxml/widgets/control.cpp b/src/dialogxml/widgets/control.cpp index 5b10f089..37c91086 100644 --- a/src/dialogxml/widgets/control.cpp +++ b/src/dialogxml/widgets/control.cpp @@ -11,7 +11,9 @@ #include "dialog.hpp" #include "sounds.hpp" #include "button.hpp" +#include "led.hpp" #include "render_shapes.hpp" +#include "render_text.hpp" #include "res_image.hpp" #include "mathutil.hpp" #include "prefs.hpp" diff --git a/src/dialogxml/widgets/control.hpp b/src/dialogxml/widgets/control.hpp index dc354565..2c7c957a 100644 --- a/src/dialogxml/widgets/control.hpp +++ b/src/dialogxml/widgets/control.hpp @@ -18,11 +18,19 @@ #include #include #include +#include #include -#include "dialog.hpp" +#include "dlogevt.hpp" #include "location.hpp" +// TinyXML forward declarations +namespace ticpp { + class Attribute; + class Element; + class Node; +} + /// Formatting properties enum eFormat { TXT_FRAME, ///< The control's frame style. Should be an enum from @ref eFrameStyle. @@ -450,52 +458,4 @@ private: std::string anchor; }; -/// A superclass to represent a control that contains other controls. -class cContainer : public cControl { - void callHandler(event_fcn::type onClick, cDialog& me, std::string id, eKeyMod mods) override; - std::string clicking; -protected: - /// Parses a child control. - /// @param elem The element defining the control. - /// @param controls The map into which the control will be inserted. - /// @param[out] The ID of the new control. - /// @return true if the element was a valid control, false otherwise. - bool parseChildControl(ticpp::Element& elem, std::map& controls, std::string& id); -public: - /// Create a new container control attached to an arbitrary window, rather than a dialog. - /// @param t The type of the control. - /// @param p The parent window. - cContainer(eControlType t, sf::RenderWindow& p) : cControl(t, p) {} - /// Create a new container control attached to a dialog. - /// @param t The type of the control. - /// @param p The parent dialog. - cContainer(eControlType t, cDialog& p) : cControl(t, p) {} - /// Check if a control exists with a given ID. - /// @param id The unique key of the control. - /// @return true if it exists. - virtual bool hasChild(std::string id) = 0; - /// Get a reference to a child control. - /// @param id The unique key of the control. - /// @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 callback) = 0; - /// @copydoc getChild() - cControl& operator[](std::string id) {return getChild(id);} - bool isContainer() override {return true;} - bool handleClick(location where) override; -}; - -// 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 void cDialog::attachEventHandlers(typename event_fcn::type handler, const std::vector& controls) { - cDialog& me = *this; - for(std::string control : controls) { - me[control].attachEventHandler(handler); - } -} - #endif diff --git a/src/dialogxml/widgets/led.cpp b/src/dialogxml/widgets/led.cpp new file mode 100644 index 00000000..d4f9e755 --- /dev/null +++ b/src/dialogxml/widgets/led.cpp @@ -0,0 +1,154 @@ + +/* + * led.cpp + * BoE + * + * Created by Celtic Minstrel on 2020-12-21. + * + */ + +#include "led.hpp" + +#include "dialog.hpp" +#include "render_image.hpp" + +#include "res_image.hpp" + +rectangle cLed::ledRects[3][2]; + +void cLed::init(){ + rectangle baseLed = {0,0,10,14}; + for(int i = 0; i < 3; i++) + for(int j = 0; j < 2; j++){ + ledRects[i][j] = baseLed; + ledRects[i][j].offset(i * 14, j * 10); + } +} + +cLed::cLed(cDialog& parent) : + cButton(parent,CTRL_LED), + state(led_off), + textFont(FONT_BOLD), + textSize(10) { + type = BTN_LED; + using namespace std::placeholders; + attachEventHandler(std::bind(&cLed::defaultClickHandler, this, _1, _2, _3)); +} + +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::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)){ + state = oldState; + } +} + +bool cLed::manageFormat(eFormat prop, bool set, boost::any* val) { + switch(prop) { + case TXT_FONT: + if(val) { + if(set) textFont = boost::any_cast(*val); + else *val = textFont; + } + break; + case TXT_SIZE: + if(val) { + if(set) textSize = boost::any_cast(*val); + else *val = textSize; + } + break; + case TXT_WRAP: + if(val) { + if(set) wrapLabel = boost::any_cast(*val); + else *val = wrapLabel; + } + break; + case TXT_COLOUR: + if(val) { + if(set) textClr = boost::any_cast(*val); + else *val = textClr; + } + break; + default: return false; + } + return true; +} + +void cLed::draw(){ + rectangle from_rect, to_rect; + + inWindow->setActive(); + + if(visible){ + TextStyle style; + style.pointSize = textSize; + style.lineHeight = textSize - 1; + style.font = textFont; + from_rect = ledRects[state][depressed]; + to_rect = frame; + to_rect.right = to_rect.left + 14; + to_rect.bottom = to_rect.top + 10; + rect_draw_some_item(*ResMgr::graphics.get(buttons[btnGW[BTN_LED]]),from_rect,*inWindow,to_rect); + style.colour = textClr; + to_rect.right = frame.right; + to_rect.left = frame.left + 18; // Possibly could be 20 + win_draw_string(*inWindow,to_rect,lbl,wrapLabel ? eTextMode::WRAP : eTextMode::LEFT_TOP,style); + } +} + +cControl::storage_t cLed::store() { + storage_t storage = cButton::store(); + storage["led-state"] = getState(); + return storage; +} + +void cLed::restore(storage_t to) { + cButton::restore(to); + if(to.find("led-state") != to.end()) + setState(boost::any_cast(to["led-state"])); + else setState(led_off); +} + +cLed::~cLed() {} + +void cLed::setState(eLedState to){ + state = to; +} + +eLedState cLed::getState(){ + return state; +} + +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; + } + 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); +} + +location cLed::getPreferredSize() { + return {ledRects[0][0].width(), ledRects[0][0].height()}; +} diff --git a/src/dialogxml/widgets/led.hpp b/src/dialogxml/widgets/led.hpp new file mode 100644 index 00000000..76cbdd59 --- /dev/null +++ b/src/dialogxml/widgets/led.hpp @@ -0,0 +1,67 @@ +/* + * led.hpp + * BoE + * + * Created by Celtic Minstrel on 2020-12-21. + * + */ + +#ifndef BOE_DIALOG_LED_HPP +#define BOE_DIALOG_LED_HPP + +#include "button.hpp" +#include "render_text.hpp" + +/// Represents the state of an LED button. +/// Generally, led_red is used to indicate a selected button. +/// Currently, led_green is only used by the spell selection dialog, +/// where led_red indicates the spell is available amd led_green indicates it is selected. +enum eLedState {led_green = 0, led_red, led_off}; + +/// A LED button that can be either on or off. +/// Additionally, it supports two possible colours, red and green. +/// By default, it behaves like a checkbox, turning on or off when clicked. +/// This default behaviour always assumes a red LED. +class cLed : public cButton { +public: + /// @copydoc cDialog::init() + static void init(); + /// A handler that can be attached as a click handler to prevent the + /// default toggle-selected action of an LED. + /// @return true to indicate the event should continue. + static bool noAction(cDialog&,std::string,eKeyMod) {return true;} + 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; + location getPreferredSize() override; + storage_t store() override; + void restore(storage_t to) override; + /// Create a new LED button. + /// @param parent The parent dialog. + explicit cLed(cDialog& parent); + virtual ~cLed(); + /// Set the LED's current state,. + /// @param to The new state. + void setState(eLedState to); + /// Get the LED's current state. + /// @return The current state. + eLedState getState(); + void draw() override; + /// @copydoc cControl::getSupportedHandlers + /// + /// @todo Document possible handlers + const std::set getSupportedHandlers() const override { + 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::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; + static rectangle ledRects[3][2]; +}; + +#endif diff --git a/src/dialogxml/widgets/ledgroup.cpp b/src/dialogxml/widgets/ledgroup.cpp new file mode 100644 index 00000000..1184c1ee --- /dev/null +++ b/src/dialogxml/widgets/ledgroup.cpp @@ -0,0 +1,247 @@ + +/* + * ledgroup.cpp + * BoE + * + * Created by Celtic Minstrel on 2020-12-21. + * + */ + +#include "ledgroup.hpp" + +#include "dialog.hpp" + +cLedGroup::cLedGroup(cDialog& parent) : + cContainer(CTRL_GROUP,parent), + fromList("none") {} + +cLedGroup::~cLedGroup(){ + ledIter iter = choices.begin(); + while(iter != choices.end()){ + delete iter->second; + iter++; + } +} + +void cLedGroup::recalcRect(){ + ledIter iter = choices.begin(); + frame = {INT_MAX, INT_MAX, 0, 0}; + while(iter != choices.end()){ + rectangle otherFrame = iter->second->getBounds(); + if(otherFrame.right > frame.right) + frame.right = otherFrame.right; + if(otherFrame.bottom > frame.bottom) + frame.bottom = otherFrame.bottom; + if(otherFrame.left < frame.left) + frame.left = otherFrame.left; + if(otherFrame.top < frame.top) + frame.top = otherFrame.top; + iter++; + } + frame.inset(-6,-6); +} + +void cLedGroup::addChoice(cLed* ctrl, std::string key) { + choices[key] = ctrl; + if(ctrl->getState() != led_off) + setSelected(key); +} + +bool cLedGroup::handleClick(location where) { + std::string which_clicked; + ledIter iter = choices.begin(); + while(iter != choices.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; +} + +void cLedGroup::callHandler(event_fcn::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); + if(!curSelect.empty()) { + choices[curSelect]->setState(led_off); + if(!choices[curSelect]->triggerFocusHandler(me,curSelect,true)){ + choices[curSelect]->setState(led_red); + return; + } + } + choices[which_clicked]->setState(led_red); + if(!choices[which_clicked]->triggerFocusHandler(me,which_clicked,false)){ + if(!curSelect.empty()) + choices[curSelect]->setState(led_red); + choices[which_clicked]->setState(led_off); + return; + } + }else return; + + std::string savePrevSelect = prevSelect; + prevSelect = curSelect; + curSelect = which_clicked; + if(!triggerFocusHandler(me,id,false)) { + if(!curSelect.empty()) + choices[curSelect]->setState(led_red); + choices[which_clicked]->setState(led_off); + curSelect = prevSelect; + prevSelect = savePrevSelect; + return; + } + return; +} + +void cLedGroup::attachFocusHandler(std::function f) { + if(!f) { + attachEventHandler(nullptr); + return; + } + using namespace std::placeholders; + attachEventHandler([f](cDialog& me, std::string id) { + f(me, id, false); + }); +} + +void cLedGroup::disable(std::string /*id*/) { + // TODO: Implement this +} + +void cLedGroup::enable(std::string /*id*/) { + // TODO: Implement this +} + +void cLedGroup::show(std::string id){ + choices[id]->show(); +} + +void cLedGroup::hide(std::string id){ + choices[id]->hide(); +} + +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(); +} + +cLed& cLedGroup::getChild(std::string id){ + ledIter iter = choices.find(id); + if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup."); + return *(iter->second); +} + +void cLedGroup::setSelected(std::string id){ + if(id == "") { // deselect all + if(curSelect == "") return; + eLedState was = choices[curSelect]->getState(); + choices[curSelect]->setState(led_off); + if(choices[curSelect]->triggerFocusHandler(*parent,curSelect,true)) + curSelect = ""; + else + choices[curSelect]->setState(was); + return; + } + + ledIter iter = choices.find(id); + if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup."); + + if(curSelect == ""){ + if(iter->second->triggerFocusHandler(*parent,curSelect,false)){ + iter->second->setState(led_red); + curSelect = iter->first; + } + }else{ + eLedState a, b; + a = choices[curSelect]->getState(); + b = iter->second->getState(); + choices[curSelect]->setState(led_off); + iter->second->setState(led_red); + if(!choices[curSelect]->triggerFocusHandler(*parent,curSelect,true)){ + choices[curSelect]->setState(a); + iter->second->setState(b); + return; + } + if(!iter->second->triggerFocusHandler(*parent,curSelect,false)){ + choices[curSelect]->setState(a); + iter->second->setState(b); + return; + } + curSelect = iter->first; + } +} + +std::string cLedGroup::getSelected(){ + return curSelect; +} + +std::string cLedGroup::getPrevSelection(){ + return prevSelect; +} + +void cLedGroup::draw(){ + if(!visible) return; + ledIter iter = choices.begin(); + while(iter != choices.end()){ + iter->second->draw(); + iter++; + } + drawFrame(2, frameStyle); +} + +cControl::storage_t cLedGroup::store() { + storage_t storage = cControl::store(); + storage["led-select"] = getSelected(); + return storage; +} + +void cLedGroup::restore(storage_t to) { + cControl::restore(to); + if(to.find("led-select") != to.end()) + setSelected(boost::any_cast(to["led-select"])); + else setSelected(""); +} + +void cLedGroup::forEach(std::function callback) { + for(auto ctrl : choices) + callback(ctrl.first, *ctrl.second); +} + +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(dynamic_cast(content)); + addChoice(led.second, led.first); + return true; + } else if(type == TiXmlNode::TEXT) { + return false; + } + return cContainer::parseContent(content, n, tagName, fname, text); +} + +void cLedGroup::validatePostParse(ticpp::Element& who, std::string fname, const std::set& attrs, const std::multiset& nodes) { + // Don't defer to super-class; groups are an abstract container that doesn't require a position. + //cControl::validatePostParse(who, fname, attrs, nodes); + frameStyle = FRM_NONE; +} diff --git a/src/dialogxml/widgets/ledgroup.hpp b/src/dialogxml/widgets/ledgroup.hpp new file mode 100644 index 00000000..3d8b4047 --- /dev/null +++ b/src/dialogxml/widgets/ledgroup.hpp @@ -0,0 +1,116 @@ +/* + * ledgroup.hpp + * BoE + * + * Created by Celtic Minstrel on 2020-12-21. + * + */ + +#ifndef BOE_DIALOG_LEDGROUP_HPP +#define BOE_DIALOG_LEDGROUP_HPP + +#include +#include +#include "led.hpp" +#include "container.hpp" + +/// A group of LED buttons that behave like radio buttons. +/// As with other standard LEDs, this always assumes red LEDs. +/// +/// When an LED in the group is clicked, the following sequence of events are fired: +/// +/// 1. The click handler of the clicked LED. +/// 2. The click handler of the LED group. +/// 3. The focus handler of the currently selected LED (if any), with the third parameter true. +/// 4. The focus handler of the clicked LED, with the third parameter false. +/// 5. The focus handler of the LED group, with the third parameter false. +/// +/// If at any stage a handler returns false, the entire sequence is aborted, and the +/// selection is not changed. A click within the group's space but not on any choice +/// triggers no events. +/// @note When the focus handlers of the individual LEDs are called, the selection has not yet been updated, +/// so calling the LED group's getSelected() method will still return the previous selection. +/// 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 { + std::map choices; + std::string fromList; + std::string curSelect, prevSelect; + std::string clicking; + void callHandler(event_fcn::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 f) 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& attrs, const std::multiset& 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. + /// + /// 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. + const std::set getSupportedHandlers() const override { + return {EVT_CLICK, EVT_FOCUS}; + } + storage_t store() override; + void restore(storage_t to) override; + /// Add a new LED to this group. + /// @param ctrl A pointer to the LED, which should already be constructed. + /// @param key A key to be used to look up the LED later. + /// @note This function is intended for internal use, which is why it takes a control pointer instead of a unique key. + void addChoice(cLed* ctrl, std::string key); + /// Disable one of the choices in this group. + /// @param id The unique key of the choice. + void disable(std::string id); + /// Enable one of the choices in this group. + /// @param id The unique key of the choice. + void enable(std::string id); + using cControl::show; + using cControl::hide; + /// Hide one of the choices in this group. + /// @param id The unique key of the choice. + void hide(std::string id); + /// Show one of the choices in this group. + /// @param id The unique key of the choice. + void show(std::string id); + /// Create a new LED group. + /// @param parent The parent dialog. + explicit cLedGroup(cDialog& parent); + bool isClickable() override; + bool isFocusable() override; + bool isScrollable() override; + bool handleClick(location where) override; + virtual ~cLedGroup(); + /// Get one of the LEDs in this group. + /// @param id The unique key of the choice. + /// @return A reference to the LED object. + /// @throw std::invalid_argument if the choice does not exist in the group. + cLed& getChild(std::string id) override; + bool hasChild(std::string id) override; + /// Set the currently selected LED in this group. + /// @param id The unique key of the choice. + /// @throw std::invalid_argument if the choice does not exist in the group. + void setSelected(std::string id); + /// Get the currently selected choice. + /// @return id The unique key of the choice. + std::string getSelected(); + /// Get the previously selected choice. + /// @return id The unique key of the choice. + /// @note This is intended for use by focus handlers. + /// + /// This refers to the element that was last selected before the selection changed to the current selection. + std::string getPrevSelection(); + /// Recalculate the LED group's bounding rect. + /// 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() override; + void forEach(std::function callback) override; + /// A convenience type for making an iterator into the choice map. + typedef std::map::iterator ledIter; + void draw() override; +}; +#endif diff --git a/src/dialogxml/widgets/scrollbar.cpp b/src/dialogxml/widgets/scrollbar.cpp index 16a12acd..60043d9b 100644 --- a/src/dialogxml/widgets/scrollbar.cpp +++ b/src/dialogxml/widgets/scrollbar.cpp @@ -7,6 +7,7 @@ // #include "scrollbar.hpp" +#include "dialog.hpp" #include "res_image.hpp" #include "render_image.hpp" #include "render_shapes.hpp" diff --git a/src/dialogxml/widgets/scrollpane.cpp b/src/dialogxml/widgets/scrollpane.cpp index 4cf998fe..4ce403fa 100644 --- a/src/dialogxml/widgets/scrollpane.cpp +++ b/src/dialogxml/widgets/scrollpane.cpp @@ -10,6 +10,7 @@ #include "message.hpp" #include "field.hpp" #include "button.hpp" +#include "dialog.hpp" #include "pict.hpp" #include "stack.hpp" #include "render_shapes.hpp" @@ -26,20 +27,6 @@ bool cScrollPane::handleClick(location where) { 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() { auto iter = contents.begin(); globalFrame = {INT_MAX, INT_MAX, 0, 0}; diff --git a/src/dialogxml/widgets/scrollpane.hpp b/src/dialogxml/widgets/scrollpane.hpp index 9c834ca0..57fe834e 100644 --- a/src/dialogxml/widgets/scrollpane.hpp +++ b/src/dialogxml/widgets/scrollpane.hpp @@ -13,6 +13,7 @@ /// Scroll-pane-related classes and types #include "scrollbar.hpp" +#include "container.hpp" /// A container element that has a fixed viewport and a vertical scrollbar. class cScrollPane : public cContainer { diff --git a/src/dialogxml/widgets/stack.cpp b/src/dialogxml/widgets/stack.cpp index 074f4c5f..51054ec2 100644 --- a/src/dialogxml/widgets/stack.cpp +++ b/src/dialogxml/widgets/stack.cpp @@ -9,6 +9,7 @@ #include "stack.hpp" #include "field.hpp" #include "button.hpp" +#include "dialog.hpp" #include "message.hpp" #include "pict.hpp" #include "scrollbar.hpp" @@ -23,15 +24,6 @@ cControl& cStack::getChild(std::string id) { return *controls[id]; } -void cContainer::callHandler(event_fcn::type onClick, cDialog& me, std::string id, eKeyMod mods) { - std::string which_clicked = clicking; - clicking = ""; - - if(onClick) onClick(me, id, mods); - if(!which_clicked.empty()) - getChild(which_clicked).triggerClickHandler(me, which_clicked, mods); -} - bool cStack::manageFormat(eFormat prop, bool set, boost::any* val) { switch(prop) { case TXT_FRAME: diff --git a/src/dialogxml/widgets/stack.hpp b/src/dialogxml/widgets/stack.hpp index b9b8e057..b7f2590c 100644 --- a/src/dialogxml/widgets/stack.hpp +++ b/src/dialogxml/widgets/stack.hpp @@ -12,7 +12,7 @@ #include #include #include -#include "control.hpp" +#include "container.hpp" /// A stack groups several controls that represent an array of data. /// Generally, each control would represent some aspect of a single element of the data. diff --git a/src/game/boe.dlgutil.cpp b/src/game/boe.dlgutil.cpp index a2eb7387..fae6f9aa 100644 --- a/src/game/boe.dlgutil.cpp +++ b/src/game/boe.dlgutil.cpp @@ -30,6 +30,7 @@ #include "res_strings.hpp" #include "scrollbar.hpp" #include "button.hpp" +#include "ledgroup.hpp" #include "pict.hpp" #include "stack.hpp" #include diff --git a/src/game/boe.graphics.cpp b/src/game/boe.graphics.cpp index 048129c4..8a17ae1e 100644 --- a/src/game/boe.graphics.cpp +++ b/src/game/boe.graphics.cpp @@ -17,6 +17,7 @@ #include "boe.text.hpp" #include "render_image.hpp" #include "render_shapes.hpp" +#include "render_text.hpp" #include "tiling.hpp" #include "sounds.hpp" #include "mathutil.hpp" diff --git a/src/game/boe.newgraph.cpp b/src/game/boe.newgraph.cpp index c564c3cf..69a892fe 100644 --- a/src/game/boe.newgraph.cpp +++ b/src/game/boe.newgraph.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "boe.global.hpp" @@ -18,6 +19,7 @@ #include "mathutil.hpp" #include "render_image.hpp" #include "render_shapes.hpp" +#include "render_text.hpp" #include "tiling.hpp" #include "utility.hpp" #include "scrollbar.hpp" diff --git a/src/pcedit/pc.editors.cpp b/src/pcedit/pc.editors.cpp index 9c344176..589e1f52 100644 --- a/src/pcedit/pc.editors.cpp +++ b/src/pcedit/pc.editors.cpp @@ -6,6 +6,7 @@ #include "dialog.hpp" #include "control.hpp" #include "button.hpp" +#include "ledgroup.hpp" #include "pict.hpp" #include "strdlog.hpp" #include "choicedlog.hpp" diff --git a/src/scenedit/scen.townout.cpp b/src/scenedit/scen.townout.cpp index 860af8f5..c7423b67 100644 --- a/src/scenedit/scen.townout.cpp +++ b/src/scenedit/scen.townout.cpp @@ -19,6 +19,7 @@ #include "strdlog.hpp" #include "choicedlog.hpp" #include "winutil.hpp" +#include "ledgroup.hpp" #include "stack.hpp" #include "scrollpane.hpp" #include "fileio.hpp" diff --git a/src/view_dialogs.cpp b/src/view_dialogs.cpp index 3266e04b..9e08462d 100644 --- a/src/view_dialogs.cpp +++ b/src/view_dialogs.cpp @@ -11,6 +11,7 @@ #include "dialog.hpp" #include "pict.hpp" #include "button.hpp" +#include "led.hpp" #include "item.hpp" #include "creature.hpp"