Split out cContainer, cLed, and cLedGroup into their own files

This commit is contained in:
2020-12-21 17:16:15 -05:00
parent 9356c03cc7
commit f14c99f14b
35 changed files with 963 additions and 666 deletions

View File

@@ -192,6 +192,7 @@
<Xml Include="..\..\..\rsrc\dialogs\welcome.xml" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\dialogxml\keycodes.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\dialogs\3choice.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\dialogs\choicedlog.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\dialogs\dialog.cpp" />
@@ -200,8 +201,11 @@
<ClCompile Include="..\..\..\src\dialogxml\dialogs\strdlog.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\basicbtns.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\button.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\container.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\control.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\field.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\led.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\ledgroup.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\message.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\pict.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\scrollbar.cpp" />
@@ -267,17 +271,20 @@
<ItemGroup>
<ClInclude Include="..\..\..\src\alchemy.hpp" />
<ClInclude Include="..\..\..\src\damage.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\keycodes.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\3choice.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\choicedlog.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.keys.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dlogevt.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\pictchoice.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\strchoice.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\strdlog.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\button.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\container.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\control.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\field.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\led.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\ledgroup.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\message.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\pict.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\pictypes.hpp" />

View File

@@ -731,6 +731,9 @@
<ClCompile Include="..\..\..\src\fileio\resmgr\res_strings.cpp">
<Filter>FileIO\ResMgr</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\keycodes.cpp">
<Filter>DialogXML</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\stack.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
@@ -746,12 +749,21 @@
<ClCompile Include="..\..\..\src\dialogxml\widgets\message.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\ledgroup.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\led.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\field.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\control.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\container.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\button.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
@@ -947,12 +959,21 @@
<ClInclude Include="..\..\..\src\dialogxml\widgets\message.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\ledgroup.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\led.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\field.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\control.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\container.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\button.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
@@ -968,15 +989,15 @@
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dlogevt.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.keys.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\dialogs\choicedlog.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\keycodes.hpp">
<Filter>DialogXML</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\tools\enum_map.hpp">
<Filter>Tools</Filter>
</ClInclude>

View File

@@ -326,6 +326,7 @@
<None Include="..\..\..\src\scenario\town_import.tpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\dialogxml\keycodes.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\dialogs\3choice.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\dialogs\choicedlog.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\dialogs\dialog.cpp" />
@@ -334,8 +335,11 @@
<ClCompile Include="..\..\..\src\dialogxml\dialogs\strdlog.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\basicbtns.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\button.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\container.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\control.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\field.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\led.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\ledgroup.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\message.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\pict.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\widgets\scrollbar.cpp" />
@@ -396,17 +400,20 @@
<ItemGroup>
<ClInclude Include="..\..\..\src\alchemy.hpp" />
<ClInclude Include="..\..\..\src\damage.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\keycodes.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\3choice.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\choicedlog.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.keys.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dlogevt.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\pictchoice.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\strchoice.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\dialogs\strdlog.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\button.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\container.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\control.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\field.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\led.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\ledgroup.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\message.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\pict.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\widgets\pictypes.hpp" />

View File

@@ -721,6 +721,9 @@
<ClCompile Include="..\..\..\src\spell.cpp" />
<ClCompile Include="..\..\..\src\utility.cpp" />
<ClCompile Include="..\..\..\src\view_dialogs.cpp" />
<ClCompile Include="..\..\..\src\dialogxml\keycodes.cpp">
<Filter>DialogXML</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\dialogs\3choice.cpp">
<Filter>DialogXML\Dialogs</Filter>
</ClCompile>
@@ -745,12 +748,21 @@
<ClCompile Include="..\..\..\src\dialogxml\widgets\button.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\container.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\control.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\field.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\led.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\ledgroup.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dialogxml\widgets\message.cpp">
<Filter>DialogXML\Widgets</Filter>
</ClCompile>
@@ -935,6 +947,9 @@
<ClInclude Include="..\..\..\src\spell.hpp" />
<ClInclude Include="..\..\..\src\utility.hpp" />
<ClInclude Include="..\..\..\src\view_dialogs.hpp" />
<ClInclude Include="..\..\..\src\dialogxml\keycodes.hpp">
<Filter>DialogXML</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\dialogs\3choice.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
@@ -944,9 +959,6 @@
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dialog.keys.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\dialogs\dlogevt.hpp">
<Filter>DialogXML\Dialogs</Filter>
</ClInclude>
@@ -962,12 +974,21 @@
<ClInclude Include="..\..\..\src\dialogxml\widgets\button.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\container.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\control.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\field.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\led.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\ledgroup.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dialogxml\widgets\message.hpp">
<Filter>DialogXML\Widgets</Filter>
</ClInclude>

View File

@@ -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 = "<group>"; };
914698FE1A747C4500F20F5E /* creature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = creature.cpp; sourceTree = "<group>"; };
914701A918F64A85008A6DC9 /* dialog.xsd */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = dialog.xsd; sourceTree = "<group>"; };
9149924525913E3F00B5BE97 /* container.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = container.cpp; sourceTree = "<group>"; };
9149924625913E3F00B5BE97 /* container.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = container.hpp; sourceTree = "<group>"; };
9149924725913E3F00B5BE97 /* led.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = led.cpp; sourceTree = "<group>"; };
9149924825913E3F00B5BE97 /* led.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = led.hpp; sourceTree = "<group>"; };
9149924925913E3F00B5BE97 /* ledgroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ledgroup.cpp; sourceTree = "<group>"; };
9149924A25913E3F00B5BE97 /* ledgroup.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ledgroup.hpp; sourceTree = "<group>"; };
91499251259140FF00B5BE97 /* keycodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keycodes.cpp; sourceTree = "<group>"; };
91499252259140FF00B5BE97 /* keycodes.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = keycodes.hpp; sourceTree = "<group>"; };
914B2AA118E7E500007B6799 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
914B2AA218E7E500007B6799 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
914B2BB518E892AA007B6799 /* dialog-converting.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "dialog-converting.txt"; sourceTree = "<group>"; };
@@ -660,7 +676,6 @@
9185BDA61EA055180027C346 /* res_font.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = res_font.hpp; sourceTree = "<group>"; };
9185BDA71EA055180027C346 /* res_sound.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = res_sound.hpp; sourceTree = "<group>"; };
9185BDA81EA055180027C346 /* res_strings.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = res_strings.hpp; sourceTree = "<group>"; };
918D59A718EA513900735B66 /* dialog.keys.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = dialog.keys.hpp; sourceTree = "<group>"; };
919086DF1A65C8E30071F7A0 /* tinyprint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tinyprint.cpp; sourceTree = "<group>"; };
919086E11A65D3250071F7A0 /* tinyprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tinyprint.h; sourceTree = "<group>"; };
919145FB18E3A32F005CF3A4 /* boe.appleevents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = boe.appleevents.mm; sourceTree = "<group>"; };
@@ -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;
};

View File

@@ -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")

View File

@@ -14,7 +14,7 @@
#include <array>
#include <boost/optional.hpp>
#include "dialog.keys.hpp"
#include "keycodes.hpp"
#include "choicedlog.hpp"
#include "button.hpp"
#include "pictypes.hpp"

View File

@@ -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<std::string,cControl*>& controls, std::string& id) {
std::string tag = elem.Value();
if(tag == "field") {
auto field = parent->parse<cTextField>(elem);
controls.insert(field);
parent->tabOrder.push_back(field);
id = field.first;
} else if(tag == "text") {
auto text = parent->parse<cTextMsg>(elem);
controls.insert(text);
id = text.first;
} else if(tag == "pict") {
auto pict = parent->parse<cPict>(elem);
controls.insert(pict);
id = pict.first;
} else if(tag == "slider") {
auto slide = parent->parse<cScrollbar>(elem);
controls.insert(slide);
id = slide.first;
} else if(tag == "button") {
auto button = parent->parse<cButton>(elem);
controls.insert(button);
id = button.first;
} else if(tag == "led") {
auto led = parent->parse<cLed>(elem);
controls.insert(led);
id = led.first;
} else if(tag == "group") {
auto group = parent->parse<cLedGroup>(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++) {

View File

@@ -21,7 +21,7 @@
#include <functional>
#include "ticpp.h"
#include "dialog.keys.hpp"
#include "keycodes.hpp"
#include "dlogevt.hpp"
#include "location.hpp"
#include <boost/any.hpp>
@@ -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<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

View File

@@ -12,7 +12,7 @@
#include <functional>
#include <string>
#include <type_traits>
#include "dialog.keys.hpp"
#include "keycodes.hpp"
/// Represents an event that can occur in a dialog.
enum eDlogEvt {

View File

@@ -14,7 +14,7 @@
#include <utility>
#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.

View File

@@ -13,7 +13,7 @@
#include <vector>
#include <functional>
#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.

116
src/dialogxml/keycodes.cpp Normal file
View File

@@ -0,0 +1,116 @@
/*
* control.cpp
* BoE
*
* Created by Celtic Minstrel on 11/05/09.
*
*/
#include "keycodes.hpp"
//#include <sstream>
//#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 - ' '];
}

View File

@@ -8,16 +8,10 @@
*/
#include "button.hpp"
#include <vector>
#include <map>
#include <stdexcept>
#include <algorithm>
#include "dialog.hpp"
#include "render_image.hpp"
#include <cmath>
#include <climits>
#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<EVT_CLICK>(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<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)){
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<eFont>(*val);
else *val = textFont;
}
break;
case TXT_SIZE:
if(val) {
if(set) textSize = boost::any_cast<short>(*val);
else *val = textSize;
}
break;
case TXT_WRAP:
if(val) {
if(set) wrapLabel = boost::any_cast<bool>(*val);
else *val = wrapLabel;
}
break;
case TXT_COLOUR:
if(val) {
if(set) textClr = boost::any_cast<sf::Color>(*val);
else *val = textClr;
}
break;
default: return false;
}
return true;
}
void cLed::draw(){
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<eLedState>(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<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);
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<bool(cDialog&,std::string,bool)> f) {
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*/) {
// 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<std::string>(to["led-select"]));
else setSelected("");
}
void cLedGroup::forEach(std::function<void(std::string,cControl&)> 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<cLed>(dynamic_cast<ticpp::Element&>(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<std::string>& attrs, const std::multiset<std::string>& nodes) {
// Don't defer to super-class; groups are an abstract container that doesn't require a position.
//cControl::validatePostParse(who, fname, attrs, nodes);
frameStyle = FRM_NONE;
}

View File

@@ -9,16 +9,7 @@
#ifndef BUTTON_H
#define BUTTON_H
/// @file
/// Button-related classes and types.
#include <SFML/Graphics.hpp>
#include <string>
#include <map>
#include <vector>
#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<eDlogEvt> 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<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) override;
bool manageFormat(eFormat prop, bool set, boost::any* val) override;
eLedState state;
eFont textFont;
short textSize;
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<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) override;
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
void validatePostParse(ticpp::Element& elem, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& elems) override;
/// @copydoc cControl::attachClickHandler()
///
/// The click handler is called whenever an LED in the group is clicked, even if it's the currently selected LED.
///
/// 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<eDlogEvt> 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<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() override;
};
#endif

View File

@@ -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<std::string,cControl*>& controls, std::string& id) {
std::string tag = elem.Value();
if(tag == "field") {
auto field = parent->parse<cTextField>(elem);
controls.insert(field);
parent->tabOrder.push_back(field);
id = field.first;
} else if(tag == "text") {
auto text = parent->parse<cTextMsg>(elem);
controls.insert(text);
id = text.first;
} else if(tag == "pict") {
auto pict = parent->parse<cPict>(elem);
controls.insert(pict);
id = pict.first;
} else if(tag == "slider") {
auto slide = parent->parse<cScrollbar>(elem);
controls.insert(slide);
id = slide.first;
} else if(tag == "button") {
auto button = parent->parse<cButton>(elem);
controls.insert(button);
id = button.first;
} else if(tag == "led") {
auto led = parent->parse<cLed>(elem);
controls.insert(led);
id = led.first;
} else if(tag == "group") {
auto group = parent->parse<cLedGroup>(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<EVT_CLICK>::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);
}

View File

@@ -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<EVT_CLICK>::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<std::string,cControl*>& 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<void(std::string,cControl&)> callback) = 0;
/// @copydoc getChild()
cControl& operator[](std::string id) {return getChild(id);}
bool isContainer() override {return true;}
bool handleClick(location where) override;
};
#endif

View File

@@ -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"

View File

@@ -18,11 +18,19 @@
#include <exception>
#include <functional>
#include <set>
#include <map>
#include <boost/any.hpp>
#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<EVT_CLICK>::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<std::string,cControl*>& 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<void(std::string,cControl&)> 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<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

View File

@@ -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<EVT_CLICK>(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<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)){
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<eFont>(*val);
else *val = textFont;
}
break;
case TXT_SIZE:
if(val) {
if(set) textSize = boost::any_cast<short>(*val);
else *val = textSize;
}
break;
case TXT_WRAP:
if(val) {
if(set) wrapLabel = boost::any_cast<bool>(*val);
else *val = wrapLabel;
}
break;
case TXT_COLOUR:
if(val) {
if(set) textClr = boost::any_cast<sf::Color>(*val);
else *val = textClr;
}
break;
default: return false;
}
return true;
}
void cLed::draw(){
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<eLedState>(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()};
}

View File

@@ -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<eDlogEvt> 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<EVT_CLICK>::type onClick, cDialog& me, std::string id, eKeyMod mods) override;
bool manageFormat(eFormat prop, bool set, boost::any* val) override;
eLedState state;
eFont textFont;
short textSize;
static rectangle ledRects[3][2];
};
#endif

View File

@@ -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<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);
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<bool(cDialog&,std::string,bool)> f) {
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*/) {
// 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<std::string>(to["led-select"]));
else setSelected("");
}
void cLedGroup::forEach(std::function<void(std::string,cControl&)> 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<cLed>(dynamic_cast<ticpp::Element&>(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<std::string>& attrs, const std::multiset<std::string>& nodes) {
// Don't defer to super-class; groups are an abstract container that doesn't require a position.
//cControl::validatePostParse(who, fname, attrs, nodes);
frameStyle = FRM_NONE;
}

View File

@@ -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 <string>
#include <map>
#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<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) override;
bool parseContent(ticpp::Node& content, int n, std::string tagName, std::string fname, std::string& text) override;
void validatePostParse(ticpp::Element& elem, std::string fname, const std::set<std::string>& attrs, const std::multiset<std::string>& elems) override;
/// @copydoc cControl::attachClickHandler()
///
/// The click handler is called whenever an LED in the group is clicked, even if it's the currently selected LED.
///
/// 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<eDlogEvt> 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<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() override;
};
#endif

View File

@@ -7,6 +7,7 @@
//
#include "scrollbar.hpp"
#include "dialog.hpp"
#include "res_image.hpp"
#include "render_image.hpp"
#include "render_shapes.hpp"

View File

@@ -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};

View File

@@ -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 {

View File

@@ -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<EVT_CLICK>::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:

View File

@@ -12,7 +12,7 @@
#include <vector>
#include <map>
#include <string>
#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.

View File

@@ -30,6 +30,7 @@
#include "res_strings.hpp"
#include "scrollbar.hpp"
#include "button.hpp"
#include "ledgroup.hpp"
#include "pict.hpp"
#include "stack.hpp"
#include <boost/lexical_cast.hpp>

View File

@@ -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"

View File

@@ -2,6 +2,7 @@
#include <cstring>
#include <cstdio>
#include <vector>
#include <iostream>
#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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -11,6 +11,7 @@
#include "dialog.hpp"
#include "pict.hpp"
#include "button.hpp"
#include "led.hpp"
#include "item.hpp"
#include "creature.hpp"