diff --git a/src/BoE.xcodeproj/project.pbxproj b/src/BoE.xcodeproj/project.pbxproj index ed618dfc..37e0d563 100755 --- a/src/BoE.xcodeproj/project.pbxproj +++ b/src/BoE.xcodeproj/project.pbxproj @@ -173,7 +173,6 @@ 919CC2681B3773C200273FDA /* control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA3C0FB8DA8E001E34EA /* control.cpp */; }; 919CC2691B3773C700273FDA /* button.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA890FB8EC57001E34EA /* button.cpp */; }; 919CC26A1B3773CD00273FDA /* dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBA180FB8BECA001E34EA /* dialog.cpp */; }; - 919CC26B1B3773D300273FDA /* dlogutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBADA0FB91D2A001E34EA /* dlogutil.cpp */; }; 919CC26C1B3773D600273FDA /* field.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAB50FB91A26001E34EA /* field.cpp */; }; 919CC26D1B3773DB00273FDA /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAB90FB91ADB001E34EA /* message.cpp */; }; 919CC26E1B3773E000273FDA /* pict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 910BBAA90FB8F733001E34EA /* pict.cpp */; }; @@ -265,6 +264,11 @@ 91E128E41BC1624700C8BE1D /* ter_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E128E31BC1624700C8BE1D /* ter_legacy.cpp */; }; 91E128E61BC19DA400C8BE1D /* init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E128E51BC19DA400C8BE1D /* init.cpp */; }; 91E128E71BC1E6DD00C8BE1D /* basicbtns.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91A32BD10FDB797B00C4E957 /* basicbtns.cpp */; }; + 91E128ED1BC2076B00C8BE1D /* 3choice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E128E81BC2076B00C8BE1D /* 3choice.cpp */; }; + 91E128EE1BC2076B00C8BE1D /* choicedlog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E128E91BC2076B00C8BE1D /* choicedlog.cpp */; }; + 91E128EF1BC2076B00C8BE1D /* pictchoice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E128EA1BC2076B00C8BE1D /* pictchoice.cpp */; }; + 91E128F01BC2076B00C8BE1D /* strchoice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E128EB1BC2076B00C8BE1D /* strchoice.cpp */; }; + 91E128F11BC2076B00C8BE1D /* strdlog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E128EC1BC2076B00C8BE1D /* strdlog.cpp */; }; 91E381461B97673700F69B81 /* town_write.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E381451B97671E00F69B81 /* town_write.cpp */; }; 91E381481B97677900F69B81 /* talk_write.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E381471B97675900F69B81 /* talk_write.cpp */; }; 91E3814A1B97679800F69B81 /* out_write.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E381491B97678D00F69B81 /* out_write.cpp */; }; @@ -585,8 +589,6 @@ 910BBAB50FB91A26001E34EA /* field.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = field.cpp; sourceTree = ""; }; 910BBAB80FB91ADB001E34EA /* message.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = message.hpp; sourceTree = ""; }; 910BBAB90FB91ADB001E34EA /* message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = message.cpp; sourceTree = ""; }; - 910BBAD90FB91D2A001E34EA /* dlogutil.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = dlogutil.hpp; sourceTree = ""; }; - 910BBADA0FB91D2A001E34EA /* dlogutil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dlogutil.cpp; sourceTree = ""; }; 910D9CA31B36439100414B17 /* libboost_thread.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_thread.dylib; path = ../../../../../../usr/local/lib/libboost_thread.dylib; sourceTree = ""; }; 911F2D981B98F43B00E3102E /* libCommon.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libCommon.a; path = lib/libCommon.a; sourceTree = ""; }; 911F2D9D1B98F44700E3102E /* libCommon-Party.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libCommon-Party.a"; path = "lib/libCommon-Party.a"; sourceTree = ""; }; @@ -755,6 +757,16 @@ 91D635AF0F90E7B500674AB3 /* zakhazi.meg */ = {isa = PBXFileReference; lastKnownFileType = file; path = zakhazi.meg; sourceTree = ""; }; 91E128E31BC1624700C8BE1D /* ter_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ter_legacy.cpp; sourceTree = ""; }; 91E128E51BC19DA400C8BE1D /* init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = init.cpp; sourceTree = ""; }; + 91E128E81BC2076B00C8BE1D /* 3choice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 3choice.cpp; sourceTree = ""; }; + 91E128E91BC2076B00C8BE1D /* choicedlog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = choicedlog.cpp; sourceTree = ""; }; + 91E128EA1BC2076B00C8BE1D /* pictchoice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pictchoice.cpp; sourceTree = ""; }; + 91E128EB1BC2076B00C8BE1D /* strchoice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = strchoice.cpp; sourceTree = ""; }; + 91E128EC1BC2076B00C8BE1D /* strdlog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = strdlog.cpp; sourceTree = ""; }; + 91E128F21BC2077600C8BE1D /* 3choice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 3choice.hpp; sourceTree = ""; }; + 91E128F31BC2077700C8BE1D /* choicedlog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = choicedlog.hpp; sourceTree = ""; }; + 91E128F41BC2077700C8BE1D /* pictchoice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = pictchoice.hpp; sourceTree = ""; }; + 91E128F51BC2077700C8BE1D /* strchoice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = strchoice.hpp; sourceTree = ""; }; + 91E128F61BC2077700C8BE1D /* strdlog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = strdlog.hpp; sourceTree = ""; }; 91E1862B1B2B2AC0006A99EA /* estreams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = estreams.cpp; sourceTree = ""; }; 91E30F2A1A74819B0057C54A /* fileio_party.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fileio_party.cpp; sourceTree = ""; }; 91E30F2D1A7481C20057C54A /* fileio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fileio.cpp; sourceTree = ""; }; @@ -937,19 +949,23 @@ 910BBA140FB8BE7D001E34EA /* headers */ = { isa = PBXGroup; children = ( + 91E128F21BC2077600C8BE1D /* 3choice.hpp */, 910BBA880FB8EC57001E34EA /* button.hpp */, + 91E128F31BC2077700C8BE1D /* choicedlog.hpp */, 910BBA3B0FB8DA8E001E34EA /* control.hpp */, 910BBA170FB8BECA001E34EA /* dialog.hpp */, 918D59A718EA513900735B66 /* dialog.keys.hpp */, 915AF9E91BC04171008AEF49 /* dlogevt.hpp */, - 910BBAD90FB91D2A001E34EA /* dlogutil.hpp */, 910BBAB40FB91A26001E34EA /* field.hpp */, 910BBAB80FB91ADB001E34EA /* message.hpp */, 910BBAA80FB8F733001E34EA /* pict.hpp */, + 91E128F41BC2077700C8BE1D /* pictchoice.hpp */, 913FB40A1A5C90840067B9D2 /* pictypes.hpp */, 919145FD18E3C750005CF3A4 /* scrollbar.hpp */, 919B13A71BBE297B009905A4 /* scrollpane.hpp */, 9179A4631A4867E200FEF872 /* stack.hpp */, + 91E128F51BC2077700C8BE1D /* strchoice.hpp */, + 91E128F61BC2077700C8BE1D /* strdlog.hpp */, ); name = headers; sourceTree = ""; @@ -957,17 +973,21 @@ 910BBA150FB8BE88001E34EA /* src */ = { isa = PBXGroup; children = ( + 91E128E81BC2076B00C8BE1D /* 3choice.cpp */, 91A32BD10FDB797B00C4E957 /* basicbtns.cpp */, 910BBA890FB8EC57001E34EA /* button.cpp */, + 91E128E91BC2076B00C8BE1D /* choicedlog.cpp */, 910BBA3C0FB8DA8E001E34EA /* control.cpp */, 910BBA180FB8BECA001E34EA /* dialog.cpp */, - 910BBADA0FB91D2A001E34EA /* dlogutil.cpp */, 910BBAB50FB91A26001E34EA /* field.cpp */, 910BBAB90FB91ADB001E34EA /* message.cpp */, 910BBAA90FB8F733001E34EA /* pict.cpp */, + 91E128EA1BC2076B00C8BE1D /* pictchoice.cpp */, 9191460018E63D8E005CF3A4 /* scrollbar.cpp */, 919B13A81BBE2B54009905A4 /* scrollpane.cpp */, 9179A4641A48681800FEF872 /* stack.cpp */, + 91E128EB1BC2076B00C8BE1D /* strchoice.cpp */, + 91E128EC1BC2076B00C8BE1D /* strdlog.cpp */, ); name = src; sourceTree = ""; @@ -1794,7 +1814,6 @@ 919CC2681B3773C200273FDA /* control.cpp in Sources */, 919CC2691B3773C700273FDA /* button.cpp in Sources */, 919CC26A1B3773CD00273FDA /* dialog.cpp in Sources */, - 919CC26B1B3773D300273FDA /* dlogutil.cpp in Sources */, 919CC26C1B3773D600273FDA /* field.cpp in Sources */, 919CC26D1B3773DB00273FDA /* message.cpp in Sources */, 919CC26E1B3773E000273FDA /* pict.cpp in Sources */, @@ -1817,6 +1836,11 @@ 91960ED41BB6157A008AF8F4 /* restypes.cpp in Sources */, 915AF9E81BBF8B5C008AEF49 /* scrollpane.cpp in Sources */, 91E128E71BC1E6DD00C8BE1D /* basicbtns.cpp in Sources */, + 91E128ED1BC2076B00C8BE1D /* 3choice.cpp in Sources */, + 91E128EE1BC2076B00C8BE1D /* choicedlog.cpp in Sources */, + 91E128EF1BC2076B00C8BE1D /* pictchoice.cpp in Sources */, + 91E128F01BC2076B00C8BE1D /* strchoice.cpp in Sources */, + 91E128F11BC2076B00C8BE1D /* strdlog.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/boe.actions.cpp b/src/boe.actions.cpp index 58c3d360..338670ec 100644 --- a/src/boe.actions.cpp +++ b/src/boe.actions.cpp @@ -26,7 +26,7 @@ #include "boe.main.hpp" #include "mathutil.hpp" #include "fileio.hpp" -#include "dlogutil.hpp" +#include "choicedlog.hpp" #include "dialog.hpp" #include "scrollbar.hpp" #include "boe.menus.hpp" diff --git a/src/boe.appleevents.mm b/src/boe.appleevents.mm index f6386854..1ddca92c 100644 --- a/src/boe.appleevents.mm +++ b/src/boe.appleevents.mm @@ -10,9 +10,10 @@ #include #include #include +#include #include "fileio.hpp" #include "boe.global.hpp" -#include "dlogutil.hpp" +#include "choicedlog.hpp" extern void finish_load_party(); extern void end_startup(); diff --git a/src/boe.combat.cpp b/src/boe.combat.cpp index feb9fd6e..cd579134 100644 --- a/src/boe.combat.cpp +++ b/src/boe.combat.cpp @@ -19,7 +19,7 @@ #include "boe.graphutil.hpp" #include "boe.main.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "choicedlog.hpp" #include "boe.menus.hpp" #include "spell.hpp" diff --git a/src/boe.dlgutil.cpp b/src/boe.dlgutil.cpp index 81a12840..6a1592d3 100644 --- a/src/boe.dlgutil.cpp +++ b/src/boe.dlgutil.cpp @@ -23,7 +23,8 @@ #include "boe.infodlg.hpp" #include "graphtool.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "winutil.hpp" #include "fileio.hpp" #include "restypes.hpp" diff --git a/src/boe.fileio.cpp b/src/boe.fileio.cpp index 272d299a..442fa2e1 100644 --- a/src/boe.fileio.cpp +++ b/src/boe.fileio.cpp @@ -17,7 +17,7 @@ #include "graphtool.hpp" #include "soundtool.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "fileio.hpp" #include #include "restypes.hpp" diff --git a/src/boe.graphutil.cpp b/src/boe.graphutil.cpp index 9581803b..593f51b4 100644 --- a/src/boe.graphutil.cpp +++ b/src/boe.graphutil.cpp @@ -17,7 +17,7 @@ #include "soundtool.hpp" #include "graphtool.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" extern sf::RenderWindow mainPtr; extern rectangle windRect; diff --git a/src/boe.infodlg.cpp b/src/boe.infodlg.cpp index 13300fdf..c9879b7e 100644 --- a/src/boe.infodlg.cpp +++ b/src/boe.infodlg.cpp @@ -19,7 +19,8 @@ #include "boe.fileio.hpp" #include "boe.main.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "button.hpp" #include "fileio.hpp" #include "restypes.hpp" #include diff --git a/src/boe.items.cpp b/src/boe.items.cpp index 6e9c475e..26cc533d 100644 --- a/src/boe.items.cpp +++ b/src/boe.items.cpp @@ -20,7 +20,8 @@ #include "boe.main.hpp" #include "graphtool.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "3choice.hpp" #include "restypes.hpp" #include "message.hpp" #include diff --git a/src/boe.main.cpp b/src/boe.main.cpp index 22ab68ba..f5e38714 100644 --- a/src/boe.main.cpp +++ b/src/boe.main.cpp @@ -23,7 +23,8 @@ #include "graphtool.hpp" #include "mathutil.hpp" #include "fileio.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "scrollbar.hpp" #include "boe.menus.hpp" #include "cursors.hpp" diff --git a/src/boe.party.cpp b/src/boe.party.cpp index 5e1d7774..a87e7519 100644 --- a/src/boe.party.cpp +++ b/src/boe.party.cpp @@ -29,7 +29,9 @@ #include "boe.main.hpp" #include "graphtool.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" +#include "pictchoice.hpp" #include "winutil.hpp" #include "fileio.hpp" #include "boe.menus.hpp" diff --git a/src/boe.specials.cpp b/src/boe.specials.cpp index 69379c3e..2f5904b3 100644 --- a/src/boe.specials.cpp +++ b/src/boe.specials.cpp @@ -26,7 +26,8 @@ #include "boe.dlgutil.hpp" #include "mathutil.hpp" #include "boe.main.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "fileio.hpp" #include #include "spell.hpp" diff --git a/src/boe.startup.cpp b/src/boe.startup.cpp index b6a5284e..331fca6d 100644 --- a/src/boe.startup.cpp +++ b/src/boe.startup.cpp @@ -14,7 +14,7 @@ #include "boe.main.hpp" #include "soundtool.hpp" #include "fileio.hpp" -#include "dlogutil.hpp" +#include "choicedlog.hpp" #include "winutil.hpp" #include "boe.menus.hpp" #include "mathutil.hpp" diff --git a/src/boe.town.cpp b/src/boe.town.cpp index 988a69b3..e28f69f7 100644 --- a/src/boe.town.cpp +++ b/src/boe.town.cpp @@ -24,7 +24,7 @@ #include "mathutil.hpp" #include "boe.main.hpp" #include "graphtool.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "fileio.hpp" #include "winutil.hpp" diff --git a/src/boe.townspec.cpp b/src/boe.townspec.cpp index 29e50c60..bfe34242 100644 --- a/src/boe.townspec.cpp +++ b/src/boe.townspec.cpp @@ -14,7 +14,8 @@ #include "boe.townspec.hpp" #include "soundtool.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "winutil.hpp" #include "boe.menus.hpp" diff --git a/src/classes/outdoors.cpp b/src/classes/outdoors.cpp index b14a58a7..da5c8cf0 100644 --- a/src/classes/outdoors.cpp +++ b/src/classes/outdoors.cpp @@ -13,7 +13,7 @@ #include #include -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "oldstructs.hpp" #include "scenario.hpp" diff --git a/src/classes/party.cpp b/src/classes/party.cpp index 14ad1c85..3890e5a5 100644 --- a/src/classes/party.cpp +++ b/src/classes/party.cpp @@ -16,7 +16,7 @@ #include "scenario.hpp" #include "universe.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "oldstructs.hpp" #include "fileio.hpp" #include "mathutil.hpp" diff --git a/src/classes/regtown.cpp b/src/classes/regtown.cpp index 45dd1722..10857c46 100644 --- a/src/classes/regtown.cpp +++ b/src/classes/regtown.cpp @@ -14,7 +14,7 @@ #include #include "scenario.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "oldstructs.hpp" #include "fileio.hpp" diff --git a/src/classes/special.cpp b/src/classes/special.cpp index d9943d9c..153d5808 100644 --- a/src/classes/special.cpp +++ b/src/classes/special.cpp @@ -13,8 +13,9 @@ #include #include -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "oldstructs.hpp" +#include "graphtool.hpp" cSpecial::cSpecial(){ type = eSpecType::NONE; diff --git a/src/dialogxml/3choice.cpp b/src/dialogxml/3choice.cpp new file mode 100644 index 00000000..65c602db --- /dev/null +++ b/src/dialogxml/3choice.cpp @@ -0,0 +1,170 @@ +/* + * dlogutil.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include "3choice.hpp" + +#include +#include + +#include "mathutil.hpp" +#include "message.hpp" +#include "pict.hpp" + +cThreeChoice::cThreeChoice + (std::vector& strings, cBasicButtonType button, pic_num_t pic, ePicType t, cDialog* parent) + : cChoiceDlog(parent), type(t){ + cDialog& parentDlog = *operator->(); + parentDlog.setBg(cDialog::BG_DARK); + parentDlog.setDefTextClr(sf::Color::White); + if(type == PIC_CUSTOM_DLOG_LG || type == PIC_DLOG_LG || type == PIC_SCEN_LG) + init_strings(strings,86); + else + init_strings(strings,50); + init_buttons(button, null_btn, null_btn); + init_pict(pic); + parentDlog.recalcRect(); +} + +cThreeChoice::cThreeChoice + (std::vector& strings, std::array& buttons, pic_num_t pic, ePicType t, cDialog* parent) + : cChoiceDlog(parent), type(t){ + cDialog& parentDlog = *operator->(); + parentDlog.setBg(cDialog::BG_DARK); + parentDlog.setDefTextClr(sf::Color::White); + if(type == PIC_CUSTOM_DLOG_LG || type == PIC_DLOG_LG || type == PIC_SCEN_LG) + init_strings(strings,86); + else + init_strings(strings,50); + init_buttons(buttons[1], buttons[2], buttons[3]); + init_pict(pic); + parentDlog.recalcRect(); +} + +cThreeChoice::cThreeChoice + (std::vector& strings,std::array& buttons,pic_num_t pic,ePicType t,cDialog* parent) + : cChoiceDlog(parent), type(t){ + cDialog& parentDlog = *operator->(); + parentDlog.setBg(cDialog::BG_DARK); + parentDlog.setDefTextClr(sf::Color::White); + if(type == PIC_CUSTOM_DLOG_LG || type == PIC_DLOG_LG || type == PIC_SCEN_LG) + init_strings(strings,86); + else + init_strings(strings,50); + std::array buttonDefs; + int i = 0; + for(short j : buttons) { + if(j < 0) buttonDefs[i++] = null_btn; + else buttonDefs[i++] = basic_buttons[j]; + } + init_buttons(buttonDefs[0], buttonDefs[1], buttonDefs[2]); + init_pict(pic); + parentDlog.recalcRect(); +} + +void cThreeChoice::init_strings(std::vector& strings, unsigned short left){ + TextStyle style; + rectangle cur_text_rect = {2, left, 0, 0}; + size_t total_len = 0, str_width, str_height; + for(unsigned int i = 0; i < strings.size(); i++) + total_len += string_length(strings[i], style); + total_len = total_len * 12; + str_width = sqrt(total_len) + 20; + //print_nums(0,total_len,str_width); + if(str_width < 340) + str_width = 340; + cur_text_rect.right = cur_text_rect.left + str_width; + cDialog* me = operator->(); + for(unsigned int j = 0; j < strings.size(); j++){ + std::ostringstream sout; + sout << "str" << j + 1; + str_height = ((string_length(strings[j], style) + 60) / str_width) * 12 + 16; + cur_text_rect.bottom = cur_text_rect.top + str_height; + cTextMsg* str = new cTextMsg(*me); + str->setText(strings[j]); + me->add(str, cur_text_rect, sout.str()); + cur_text_rect.top = cur_text_rect.bottom + 8; + } + buttons_right = cur_text_rect.right + 30; + buttons_top = cur_text_rect.top; +} + +void cThreeChoice::init_buttons(cBasicButtonType btn1, cBasicButtonType btn2, cBasicButtonType btn3){ + using namespace std::placeholders; + rectangle cur_btn_rect = {buttons_top,0,0,buttons_right}; + if(btn1) btns[0] = btn1; + if(btn2) btns[1] = btn2; + if(btn3) btns[2] = btn3; + cDialog* me = operator->(); + for(int i = 0; i < 3; i++){ + if(!btns[i]) continue; + std::ostringstream sout; + sout << "btn" << i + 1; + cButton* btn = new cButton(*me); + btn->attachKey(btns[i]->defaultKey); + btn->setText(btns[i]->label); + btn->setBtnType(btns[i]->type); + btn->attachClickHandler(std::bind(&cThreeChoice::onClick,this,_1,_2)); + switch(btns[i]->type){ + case BTN_HELP: + cur_btn_rect.bottom = cur_btn_rect.top + 13; + break; + case BTN_TINY: + case BTN_LED: // BTN_LED should never occur though + cur_btn_rect.bottom = cur_btn_rect.top + 10; + break; + case BTN_TALL: + case BTN_TRAIT: + cur_btn_rect.bottom = cur_btn_rect.top + 40; + break; + case BTN_PUSH: + cur_btn_rect.bottom = cur_btn_rect.top + 30; + break; + default: // in fact, this case should be the only one reachable, ideally + cur_btn_rect.bottom = cur_btn_rect.top + 23; + } + switch(btns[i]->type){ + case BTN_SM: + cur_btn_rect.left = cur_btn_rect.right - 23; + break; + case BTN_HELP: + cur_btn_rect.left = cur_btn_rect.right - 16; + break; + case BTN_TINY: + case BTN_LED: + cur_btn_rect.left = cur_btn_rect.right - 14; + break; + case BTN_PUSH: + cur_btn_rect.left = cur_btn_rect.right - 30; + break; + case BTN_LG: + cur_btn_rect.left = cur_btn_rect.right - 102; + break; + default: + cur_btn_rect.left = cur_btn_rect.right - 63; + } + me->add(btn, cur_btn_rect, sout.str()); + cur_btn_rect.right = cur_btn_rect.left - 4; + } +} + +void cThreeChoice::init_pict(pic_num_t pic){ + cDialog* me = operator->(); + cPict* pic_ctrl = new cPict(*me); + pic_ctrl->setBounds({8,8,8,8}); + pic_ctrl->setPict(pic,type); + pic_ctrl->recalcRect(); + me->add(pic_ctrl, pic_ctrl->getBounds(), "pict"); +} + +std::string cThreeChoice::show(){ + std::string result = cChoiceDlog::show(); + if(result == "btn1") return btns[0]->label; + else if(result == "btn2") return btns[1]->label; + else if(result == "btn3") return btns[2]->label; + return "**ERROR**"; // shouldn't be reached +} diff --git a/src/dialogxml/3choice.hpp b/src/dialogxml/3choice.hpp new file mode 100644 index 00000000..e0191744 --- /dev/null +++ b/src/dialogxml/3choice.hpp @@ -0,0 +1,76 @@ +/* + * dlogutil.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef DIALOG_3CHOICE_H +#define DIALOG_3CHOICE_H + +#include +#include +#include +#include + +#include "dialog.keys.hpp" +#include "choicedlog.hpp" +#include "button.hpp" +#include "pictypes.hpp" + +/// Basic button type template +struct bbtt { + eBtnType type; ///< The type of the preset button. + std::string label; ///< The preset button's label, if any. + cKey defaultKey; ///< The preset button's default key shortcut, if any. + std::string name; ///< (optional) A more descriptive name for the button. +}; + +/// Represents a preset button for use with cThreeChoice. +typedef boost::optional cBasicButtonType; + +namespace {cBasicButtonType null_btn = boost::none;} +#ifndef BTNS_DEFINED +extern bbtt basic_buttons[71]; +#endif + +/// A choice dialog with several strings and up to three buttons. +/// This is the class used for dialogs generated by special nodes. +/// It generates the dialog dynamically from the given input. +/// Note that the dialog is not limited to six strings. +class cThreeChoice : public cChoiceDlog { + cBasicButtonType btns[3]; + unsigned short buttons_right, buttons_top; + void init_strings(std::vector& strings, unsigned short left); + void init_buttons(cBasicButtonType btn1, cBasicButtonType btn2, cBasicButtonType btn3); + void init_pict(pic_num_t pic); + const ePicType type; +public: + /// Create a dialog with just one button. + /// @param strings A list of the strings to place in the dialog. + /// @param button The specification of the button. + /// @param pic The icon to show at the top left. + /// @param t The type of the icon. + /// @param parent Optionally, a parent dialog. + cThreeChoice(std::vector& strings, cBasicButtonType button, pic_num_t pic, ePicType t, cDialog* parent = nullptr); + /// Create a dialog with up to three buttons. + /// @param strings A list of the strings to place in the dialog. + /// @param buttons A list of the button specifications. + /// @param pic The icon to show at the top left. + /// @param t The type of the icon. + /// @param parent Optionally, a parent dialog. + cThreeChoice(std::vector& strings, std::array& buttons, pic_num_t pic, ePicType t, cDialog* parent = nullptr); + /// Create a dialog with up to three buttons. + /// @param strings A list of the strings to place in the dialog. + /// @param buttons A list of the index of the button; this is an index into available_btns which is in turn used to index basic_buttons. + /// @param pic The icon to show at the top left. + /// @param t The type of the icon. + /// @param parent Optionally, a parent dialog. + cThreeChoice(std::vector& strings, std::array& buttons, pic_num_t pic, ePicType t, cDialog* parent = nullptr); + /// @copydoc cChoiceDlog::show() + /// @note The unique key in this case is the label specified in the button specification. + std::string show(); +}; + +#endif diff --git a/src/dialogxml/basicbtns.cpp b/src/dialogxml/basicbtns.cpp index c6aac434..20e2a7bf 100644 --- a/src/dialogxml/basicbtns.cpp +++ b/src/dialogxml/basicbtns.cpp @@ -7,7 +7,7 @@ */ #define BTNS_DEFINED -#include "dlogutil.hpp" +#include "3choice.hpp" /// @file /// Preset button specifications for cThreeChoice diff --git a/src/dialogxml/choicedlog.cpp b/src/dialogxml/choicedlog.cpp new file mode 100644 index 00000000..623ec7de --- /dev/null +++ b/src/dialogxml/choicedlog.cpp @@ -0,0 +1,42 @@ +/* + * dlogutil.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include "choicedlog.hpp" + +#include +#include "control.hpp" + +cChoiceDlog::cChoiceDlog(std::string file, std::vector buttons, cDialog* p) : dlg(file, p) { + using namespace std::placeholders; + std::vector::iterator iter = buttons.begin(); + while(iter != buttons.end()){ + dlg[*iter].attachClickHandler(std::bind(&cChoiceDlog::onClick,this,_1,_2)); + iter++; + } +} + +cChoiceDlog::cChoiceDlog(cDialog* p) : dlg(p) {} + +cChoiceDlog::cChoiceDlog(std::string file, cDialog* p) + : cChoiceDlog(file, {"okay"}, p) {} + +// so that the caller can set up aspects of the dialog if necessary +cDialog* cChoiceDlog::operator->(){ + return &dlg; +} + +std::string cChoiceDlog::show(){ + dlg.run(); + return dlg.getResult(); +} + +bool cChoiceDlog::onClick(cDialog& me, std::string id){ + me.setResult(id); + me.toast(true); + return true; +} diff --git a/src/dialogxml/choicedlog.hpp b/src/dialogxml/choicedlog.hpp new file mode 100644 index 00000000..318cca91 --- /dev/null +++ b/src/dialogxml/choicedlog.hpp @@ -0,0 +1,49 @@ +/* + * dlogutil.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef DIALOG_CHOICEDLOG_H +#define DIALOG_CHOICEDLOG_H + +#include +#include +#include "dialog.hpp" + +/// A simple dialog that lets you select one of several buttons. +/// This class loads a definition from a file, so there can be any amount of other stuff in the dialog, +/// and the buttons could be arranged in any fashion you want. +class cChoiceDlog { + cDialog dlg; +protected: + /// The click handler for the dialog's buttons. + /// @param me A reference to the current dialog. + /// @param id The unique key of the clicked control. + /// @return true, indicating the event should continue. + bool onClick(cDialog& me, std::string id); + /// Create a choice dialog, but don't initialize it. + /// @param p Optionally, a parent dialog. + explicit cChoiceDlog(cDialog* p = nullptr); +public: + /// Create a choice dialog with just one button. + /// @param file The file to load the dialog definition from. + /// @param p Optionally, a parent dialog. + /// @note The dialog definition file must include a button whose name attribute is "okay". + explicit cChoiceDlog(std::string file, cDialog* p = nullptr); + /// Create a choice dialog with several buttons. + /// @param file The file to load the dialog definition from. + /// @param buttons A list of the buttons to handle. All of them must be defined in the file. + /// @param p Optionally, a parent dialog. + cChoiceDlog(std::string file, std::vector buttons, cDialog* p = nullptr); + /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. + /// @return A pointer to the dialog. + cDialog* operator->(); + /// Show the dialog. + /// @return The unique key of the clicked button. + std::string show(); +}; + +#endif diff --git a/src/dialogxml/dlogutil.cpp b/src/dialogxml/dlogutil.cpp deleted file mode 100644 index 521780b9..00000000 --- a/src/dialogxml/dlogutil.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/* - * dlogutil.cpp - * BoE - * - * Created by Celtic Minstrel on 11/05/09. - * - */ - -#include -#include - -#include -#include -#include "dialog.hpp" -#include "dlogutil.hpp" -#include "winutil.hpp" -#include "mathutil.hpp" -#include -#include "message.hpp" - -cPictChoice::cPictChoice(const std::vector& pics,ePicType t,cDialog* parent) : cPictChoice(pics.begin(), pics.end(), t, parent) {} - -cPictChoice::cPictChoice(const std::vector>& pics,cDialog* parent) : dlg("choose-pict",parent) { - picts = pics; - attachHandlers(); -} - -cPictChoice::cPictChoice( - std::vector::const_iterator begin, - std::vector::const_iterator end, - ePicType t, - cDialog* parent - ) : dlg("choose-pict",parent) { - for(auto iter = begin; iter != end; iter++) { - picts.push_back({*iter,t}); - } - attachHandlers(); -} - -cPictChoice::cPictChoice(pic_num_t first, pic_num_t last, ePicType t, cDialog* parent) : dlg("choose-pict",parent) { - for(pic_num_t i = first; i <= last; i++) { - picts.push_back({i,t}); - } - attachHandlers(); -} - -void cPictChoice::attachHandlers() { - using namespace std::placeholders; - dlg["left"].attachClickHandler(std::bind(&cPictChoice::onLeft,this)); - dlg["right"].attachClickHandler(std::bind(&cPictChoice::onRight,this)); - dlg["done"].attachClickHandler(std::bind(&cPictChoice::onOkay,this)); - dlg["cancel"].attachClickHandler(std::bind(&cPictChoice::onCancel,this)); - leds = &dynamic_cast(dlg["group"]); - leds->attachFocusHandler(std::bind(&cPictChoice::onSelect,this,_3)); - if(picts.size() <= per_page) { - dlg["left"].hide(); - dlg["right"].hide(); - } -} - -cDialog* cPictChoice::operator->() { - return &dlg; -} - -bool cPictChoice::show(size_t cur_sel){ - if(cur_sel >= picts.size()) - cur_sel = 0; - cur = cur_sel; - dlg.setResult(picts[cur_sel]); - page = cur / per_page; - fillPage(); - dlg.run(); - return didAccept; -} - -void cPictChoice::attachSelectHandler(std::function f) { - select_handler = f; -} - -void cPictChoice::fillPage(){ - cLedGroup& group = dynamic_cast(dlg["group"]); - group.setSelected(""); // unselect all LEDs, since the currently selected one may be on another page - for(size_t i = 0; i < per_page; i++){ - std::ostringstream sout; - sout << "led" << i + 1; - if(page * per_page + i >= picts.size()) - dlg[sout.str()].hide(); - else - dlg[sout.str()].show(); - if(page * per_page + i == cur) - group.setSelected(sout.str()); - sout.str(""); - sout << "pic" << i + 1; - cPict& pic = dynamic_cast(dlg[sout.str()]); - if(page * per_page + i < picts.size()){ - pic.show(); - ePicType tp = picts[per_page * page + i].second; - pic.setPict(picts[per_page * page + i].first, tp); - rectangle b = pic.getBounds(); - if(tp == PIC_DLOG_LG || tp == PIC_CUSTOM_DLOG_LG || tp == PIC_SCEN_LG) { - pic.setFormat(TXT_WRAP, false); - b.width() /= 2; - b.height() /= 2; - } else if(tp == PIC_FULL) { - pic.setFormat(TXT_WRAP, false); - b.width() = 40; - b.height() = 40; - } else pic.setFormat(TXT_WRAP, true); - pic.setBounds(b); - }else pic.hide(); - } -} - -bool cPictChoice::onLeft(){ - if(page == 0) page = (picts.size() - 1) / per_page; - else page--; - fillPage(); - return true; -} - -bool cPictChoice::onRight(){ - if(page == (picts.size() - 1) / per_page) page = 0; - else page++; - fillPage(); - return true; -} - -bool cPictChoice::onCancel(){ - dlg.toast(false); - didAccept = false; - return true; -} - -bool cPictChoice::onOkay(){ - dlg.setResult(picts[cur]); - dlg.toast(true); - didAccept = true; - return true; -} - -bool cPictChoice::onSelect(bool losing) { - if(losing) return true; - int i = boost::lexical_cast(leds->getSelected().substr(3)); - cur = page * per_page + i - 1; - if(select_handler) - select_handler(*this, cur); - return true; -} - -pic_num_t cPictChoice::getPicChosen() { - return dlg.getResult>().first; -} - -ePicType cPictChoice::getPicChosenType() { - return dlg.getResult>().second; -} - -size_t cPictChoice::getSelected() { - return cur; -} - -cStringChoice::cStringChoice( - std::vector& strs, - std::string title, - cDialog* parent - ) : dlg("choose-string",parent) { - if(!title.empty()) dlg["title"].setText(title); - strings = strs; - attachHandlers(); -} - -cStringChoice::cStringChoice( - std::vector::iterator begin, - std::vector::iterator end, - std::string title, - cDialog* parent - ) : dlg("choose-string",parent) { - if(!title.empty()) dlg["title"].setText(title); - copy(begin,end,std::inserter(strings, strings.begin())); - attachHandlers(); -} - -void cStringChoice::attachHandlers() { - using namespace std::placeholders; - dlg["left"].attachClickHandler(std::bind(&cStringChoice::onLeft,this)); - dlg["right"].attachClickHandler(std::bind(&cStringChoice::onRight,this)); - dlg["done"].attachClickHandler(std::bind(&cStringChoice::onOkay,this,_1)); - dlg["cancel"].attachClickHandler(std::bind(&cStringChoice::onCancel,this,_1)); - leds = &dynamic_cast(dlg["strings"]); - leds->attachFocusHandler(std::bind(&cStringChoice::onSelect,this,_3)); - if(strings.size() <= per_page) { - dlg["left"].hide(); - dlg["right"].hide(); - } -} - -cDialog* cStringChoice::operator->() { - return &dlg; -} - -size_t cStringChoice::show(size_t selectedIndex) { - cur = selectedIndex; - if(cur >= strings.size()) cur = 0; - page = cur / per_page; - fillPage(); - dlg.setResult(selectedIndex); - dlg.run(); - return dlg.getResult(); -} - -void cStringChoice::attachSelectHandler(std::function f) { - select_handler = f; -} - -void cStringChoice::fillPage(){ - cLedGroup& group = dynamic_cast(dlg["strings"]); - group.setSelected(""); // unselect all LEDs, since the currently selected one may be on another page - for(unsigned int i = 0; i < per_page; i++){ - std::ostringstream sout; - sout << "led" << i + 1; - if(page * per_page + i >= strings.size()){ - dlg[sout.str()].hide(); - continue; - }else - dlg[sout.str()].show(); - if(page * per_page + i == cur) - group.setSelected(sout.str()); - if(page * per_page + i < strings.size()){ - dlg[sout.str()].setText(strings[per_page * page + i]); - } - } -} - -bool cStringChoice::onLeft(){ - if(page == 0) page = strings.size() / per_page; - else page--; - fillPage(); - return true; -} - -bool cStringChoice::onRight(){ - if(page == strings.size() / per_page) page = 0; - else page++; - fillPage(); - return true; -} - -bool cStringChoice::onCancel(cDialog& me){ - me.toast(false); - return true; -} - -bool cStringChoice::onOkay(cDialog& me){ - dlg.setResult(cur); - me.toast(true); - return true; -} - -bool cStringChoice::onSelect(bool losing) { - if(losing) return true; - int i = boost::lexical_cast(leds->getSelected().substr(3)); - cur = page * per_page + i - 1; - if(select_handler) - select_handler(*this, cur); - return true; -} - -cChoiceDlog::cChoiceDlog(std::string file, std::vector buttons, cDialog* p) : dlg(file, p) { - using namespace std::placeholders; - std::vector::iterator iter = buttons.begin(); - while(iter != buttons.end()){ - dlg[*iter].attachClickHandler(std::bind(&cChoiceDlog::onClick,this,_1,_2)); - iter++; - } -} - -cChoiceDlog::cChoiceDlog(cDialog* p) : dlg(p) {} - -cChoiceDlog::cChoiceDlog(std::string file, cDialog* p) - : cChoiceDlog(file, {"okay"}, p) {} - -// so that the caller can set up aspects of the dialog if necessary -cDialog* cChoiceDlog::operator->(){ - return &dlg; -} - -std::string cChoiceDlog::show(){ - dlg.run(); - return dlg.getResult(); -} - -bool cChoiceDlog::onClick(cDialog& me, std::string id){ - me.setResult(id); - me.toast(true); - return true; -} - -cThreeChoice::cThreeChoice - (std::vector& strings, cBasicButtonType button, pic_num_t pic, ePicType t, cDialog* parent) - : cChoiceDlog(parent), type(t){ - cDialog& parentDlog = *operator->(); - parentDlog.setBg(cDialog::BG_DARK); - parentDlog.setDefTextClr(sf::Color::White); - if(type == PIC_CUSTOM_DLOG_LG || type == PIC_DLOG_LG || type == PIC_SCEN_LG) - init_strings(strings,86); - else - init_strings(strings,50); - init_buttons(button, null_btn, null_btn); - init_pict(pic); - parentDlog.recalcRect(); -} - -cThreeChoice::cThreeChoice - (std::vector& strings, std::array& buttons, pic_num_t pic, ePicType t, cDialog* parent) - : cChoiceDlog(parent), type(t){ - cDialog& parentDlog = *operator->(); - parentDlog.setBg(cDialog::BG_DARK); - parentDlog.setDefTextClr(sf::Color::White); - if(type == PIC_CUSTOM_DLOG_LG || type == PIC_DLOG_LG || type == PIC_SCEN_LG) - init_strings(strings,86); - else - init_strings(strings,50); - init_buttons(buttons[1], buttons[2], buttons[3]); - init_pict(pic); - parentDlog.recalcRect(); -} - -cThreeChoice::cThreeChoice - (std::vector& strings,std::array& buttons,pic_num_t pic,ePicType t,cDialog* parent) - : cChoiceDlog(parent), type(t){ - cDialog& parentDlog = *operator->(); - parentDlog.setBg(cDialog::BG_DARK); - parentDlog.setDefTextClr(sf::Color::White); - if(type == PIC_CUSTOM_DLOG_LG || type == PIC_DLOG_LG || type == PIC_SCEN_LG) - init_strings(strings,86); - else - init_strings(strings,50); - std::array buttonDefs; - int i = 0; - for(short j : buttons) { - if(j < 0) buttonDefs[i++] = null_btn; - else buttonDefs[i++] = basic_buttons[j]; - } - init_buttons(buttonDefs[0], buttonDefs[1], buttonDefs[2]); - init_pict(pic); - parentDlog.recalcRect(); -} - -void cThreeChoice::init_strings(std::vector& strings, unsigned short left){ - TextStyle style; - rectangle cur_text_rect = {2, left, 0, 0}; - size_t total_len = 0, str_width, str_height; - for(unsigned int i = 0; i < strings.size(); i++) - total_len += string_length(strings[i], style); - total_len = total_len * 12; - str_width = sqrt(total_len) + 20; - //print_nums(0,total_len,str_width); - if(str_width < 340) - str_width = 340; - cur_text_rect.right = cur_text_rect.left + str_width; - cDialog* me = operator->(); - for(unsigned int j = 0; j < strings.size(); j++){ - std::ostringstream sout; - sout << "str" << j + 1; - str_height = ((string_length(strings[j], style) + 60) / str_width) * 12 + 16; - cur_text_rect.bottom = cur_text_rect.top + str_height; - cTextMsg* str = new cTextMsg(*me); - str->setText(strings[j]); - me->add(str, cur_text_rect, sout.str()); - cur_text_rect.top = cur_text_rect.bottom + 8; - } - buttons_right = cur_text_rect.right + 30; - buttons_top = cur_text_rect.top; -} - -void cThreeChoice::init_buttons(cBasicButtonType btn1, cBasicButtonType btn2, cBasicButtonType btn3){ - using namespace std::placeholders; - rectangle cur_btn_rect = {buttons_top,0,0,buttons_right}; - if(btn1) btns[0] = btn1; - if(btn2) btns[1] = btn2; - if(btn3) btns[2] = btn3; - cDialog* me = operator->(); - for(int i = 0; i < 3; i++){ - if(!btns[i]) continue; - std::ostringstream sout; - sout << "btn" << i + 1; - cButton* btn = new cButton(*me); - btn->attachKey(btns[i]->defaultKey); - btn->setText(btns[i]->label); - btn->setBtnType(btns[i]->type); - btn->attachClickHandler(std::bind(&cThreeChoice::onClick,this,_1,_2)); - switch(btns[i]->type){ - case BTN_HELP: - cur_btn_rect.bottom = cur_btn_rect.top + 13; - break; - case BTN_TINY: - case BTN_LED: // BTN_LED should never occur though - cur_btn_rect.bottom = cur_btn_rect.top + 10; - break; - case BTN_TALL: - case BTN_TRAIT: - cur_btn_rect.bottom = cur_btn_rect.top + 40; - break; - case BTN_PUSH: - cur_btn_rect.bottom = cur_btn_rect.top + 30; - break; - default: // in fact, this case should be the only one reachable, ideally - cur_btn_rect.bottom = cur_btn_rect.top + 23; - } - switch(btns[i]->type){ - case BTN_SM: - cur_btn_rect.left = cur_btn_rect.right - 23; - break; - case BTN_HELP: - cur_btn_rect.left = cur_btn_rect.right - 16; - break; - case BTN_TINY: - case BTN_LED: - cur_btn_rect.left = cur_btn_rect.right - 14; - break; - case BTN_PUSH: - cur_btn_rect.left = cur_btn_rect.right - 30; - break; - case BTN_LG: - cur_btn_rect.left = cur_btn_rect.right - 102; - break; - default: - cur_btn_rect.left = cur_btn_rect.right - 63; - } - me->add(btn, cur_btn_rect, sout.str()); - cur_btn_rect.right = cur_btn_rect.left - 4; - } -} - -void cThreeChoice::init_pict(pic_num_t pic){ - cDialog* me = operator->(); - cPict* pic_ctrl = new cPict(*me); - pic_ctrl->setBounds({8,8,8,8}); - pic_ctrl->setPict(pic,type); - pic_ctrl->recalcRect(); - me->add(pic_ctrl, pic_ctrl->getBounds(), "pict"); -} - -std::string cThreeChoice::show(){ - std::string result = cChoiceDlog::show(); - if(result == "btn1") return btns[0]->label; - else if(result == "btn2") return btns[1]->label; - else if(result == "btn3") return btns[2]->label; - return "**ERROR**"; // shouldn't be reached -} - -std::string cStrDlog::getFileName(short n_strs, ePicType type, bool hasTitle){ - std::ostringstream sout; - sout << n_strs << "str"; - if(hasTitle) sout << "-title"; - if(type == PIC_DLOG_LG || type == PIC_CUSTOM_DLOG_LG || type == PIC_SCEN_LG) - sout << "-lg"; - return sout.str(); -} - -cStrDlog::cStrDlog(std::string str1,std::string str2,std::string title,pic_num_t pic,ePicType t,cDialog* parent) - : dlg(cStrDlog::getFileName((str1 != "") + (str2 != ""), t, title != ""), parent), type(t) { - using namespace std::placeholders; - cPict& pic_ctrl = dynamic_cast(dlg["pict"]); - pic_ctrl.setPict(pic, type); - if(str1 != "") { - dlg["str1"].setText(str1); - if(str2 != "") dlg["str2"].setText(str2); - }else if(str2 != "") dlg["str1"].setText(str2); - if(title != "") dlg["title"].setText(title); - dlg["record"].hide(); - dlg["record"].attachClickHandler(std::bind(&cStrDlog::onRecord, this, _2)); - dlg["done"].attachClickHandler(std::bind(&cStrDlog::onDismiss, this)); -} - -bool cStrDlog::onRecord(std::string id){ - if(hasRecord) rec_f(dlg); - else dlg[id].hide(); - return hasRecord; -} - -bool cStrDlog::onDismiss(){ - dlg.toast(true); - return true; -} - -cStrDlog& cStrDlog::setSound(snd_num_t snd){ - sound = snd; - return *this; -} - -cStrDlog& cStrDlog::setRecordHandler(record_callback_t rec){ - if(rec == nullptr){ - hasRecord = false; - dlg["record"].hide(); - }else{ - hasRecord = true; - rec_f = rec; - dlg["record"].show(); - } - return *this; -} - -cDialog* cStrDlog::operator->() { - return &dlg; -} - -void cStrDlog::show(){ - if(sound > 0) play_sound(sound); - dlg.run(); -} - -static void giveError(pic_num_t pic, std::string title, std::string str1, std::string str2, cDialog* parent) { - cStrDlog error(str1,str2,title,pic,PIC_DLOG,parent); - error->getControl("record").setText("Copy"); - error.setRecordHandler([](cDialog& me) { - std::string error = me["str1"].getText(); - try { - std::string error2 = me["str2"].getText(); - error += "\n\n" + error2; - } catch(std::invalid_argument) {} - for(char& c : error) { - if(c == '|') c = '\n'; - } - set_clipboard(error); - }); - error.show(); -} - -void showError(std::string str1, cDialog* parent) { - showError(str1, "", parent); -} - -void showError(std::string str1, std::string str2, cDialog* parent) { - giveError(25, "Error", str1, str2, parent); -} - -void showWarning(std::string str1, cDialog* parent) { - showWarning(str1, "", parent); -} - -void showWarning(std::string str1, std::string str2, cDialog* parent) { - giveError(24, "Warning", str1, str2, parent); -} - -void showFatalError(std::string str1, cDialog* parent) { - showFatalError(str1, "", parent); -} - -void showFatalError(std::string str1, std::string str2, cDialog* parent) { - giveError(25, "Error!!!", str1, str2, parent); -} diff --git a/src/dialogxml/dlogutil.hpp b/src/dialogxml/dlogutil.hpp deleted file mode 100644 index 4bc34c44..00000000 --- a/src/dialogxml/dlogutil.hpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * dlogutil.h - * BoE - * - * Created by Celtic Minstrel on 11/05/09. - * - */ - -#ifndef DIALOG_UTIL_H -#define DIALOG_UTIL_H - -/// @file -/// A set of utility classes for simple and common dialogs. - -#include -#include -#include -#include -#include "pictypes.hpp" -#include "soundtool.hpp" // for snd_num_t -#include "pict.hpp" -#include "dialog.hpp" -#include "button.hpp" -#include - -/// The signature of a record handler for cStrDlog. -typedef std::function record_callback_t; - -/// A simple dialog with one or two long strings, an optional title, and an optional record button. -class cStrDlog { - static std::string getFileName(short n_strs, ePicType type, bool hasTitle); - cDialog dlg; - short sound = -1; - record_callback_t rec_f; - bool hasRecord; - const ePicType type; - bool onRecord(std::string id); - bool onDismiss(); -public: - /// Construct a string dialog. - /// @param str1 The first string. - /// @param str2 The second string. If left as an empty string, there will be only one string in the dialog. - /// @param title The title. If left as an empty string, there will be no title. - /// @param pic The icon to show at the top left. - /// @param t The type of icon to show. - /// @param parent Optionally, a parent dialog. - cStrDlog(std::string str1,std::string str2,std::string title,pic_num_t pic,ePicType t,cDialog* parent = nullptr); - /// Set a sound to be played when the dialog is shown. - /// @param num The sound number. - /// @return This object, for method-call chaining. - cStrDlog& setSound(snd_num_t num); - /// Set a record handler. - /// @param rec The handler. - /// @return This object, for method-call chaining. - /// @note Only one record handler can be set at a time. To remove it, set it to null. - /// @note The presence of the Record button is determined entirely by the presence of a record handler. - /// - /// A record handler should take one parameter, which is a reference to the dialog. - /// (That's the cDialog, not the cStrDlog.) It should return void. - cStrDlog& setRecordHandler(record_callback_t rec); - /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. - /// @return A pointer to the dialog. - cDialog* operator->(); - /// Show the dialog. - void show(); -}; - -/// A simple dialog that lets you select one of several buttons. -/// This class loads a definition from a file, so there can be any amount of other stuff in the dialog, -/// and the buttons could be arranged in any fashion you want. -class cChoiceDlog { - cDialog dlg; -protected: - /// The click handler for the dialog's buttons. - /// @param me A reference to the current dialog. - /// @param id The unique key of the clicked control. - /// @return true, indicating the event should continue. - bool onClick(cDialog& me, std::string id); - /// Create a choice dialog, but don't initialize it. - /// @param p Optionally, a parent dialog. - explicit cChoiceDlog(cDialog* p = nullptr); -public: - /// Create a choice dialog with just one button. - /// @param file The file to load the dialog definition from. - /// @param p Optionally, a parent dialog. - /// @note The dialog definition file must include a button whose name attribute is "okay". - explicit cChoiceDlog(std::string file, cDialog* p = nullptr); - /// Create a choice dialog with several buttons. - /// @param file The file to load the dialog definition from. - /// @param buttons A list of the buttons to handle. All of them must be defined in the file. - /// @param p Optionally, a parent dialog. - cChoiceDlog(std::string file, std::vector buttons, cDialog* p = nullptr); - /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. - /// @return A pointer to the dialog. - cDialog* operator->(); - /// Show the dialog. - /// @return The unique key of the clicked button. - std::string show(); -}; - -/// Basic button type template -struct bbtt { - eBtnType type; ///< The type of the preset button. - std::string label; ///< The preset button's label, if any. - cKey defaultKey; ///< The preset button's default key shortcut, if any. - std::string name; ///< (optional) A more descriptive name for the button. -}; - -/// Represents a preset button for use with cThreeChoice. -typedef boost::optional cBasicButtonType; - -namespace {cBasicButtonType null_btn = boost::none;} -#ifndef BTNS_DEFINED -extern bbtt basic_buttons[71]; -#endif - -/// A choice dialog with several strings and up to three buttons. -/// This is the class used for dialogs generated by special nodes. -/// It generates the dialog dynamically from the given input. -/// Note that the dialog is not limited to six strings. -class cThreeChoice : public cChoiceDlog { - //static std::string getFileName(size_t n_strs); - cBasicButtonType btns[3]; - unsigned short buttons_right, buttons_top; - void init_strings(std::vector& strings, unsigned short left); - void init_buttons(cBasicButtonType btn1, cBasicButtonType btn2, cBasicButtonType btn3); - void init_pict(pic_num_t pic); - const ePicType type; -public: - /// Create a dialog with just one button. - /// @param strings A list of the strings to place in the dialog. - /// @param button The specification of the button. - /// @param pic The icon to show at the top left. - /// @param t The type of the icon. - /// @param parent Optionally, a parent dialog. - cThreeChoice(std::vector& strings, cBasicButtonType button, pic_num_t pic, ePicType t, cDialog* parent = nullptr); - /// Create a dialog with up to three buttons. - /// @param strings A list of the strings to place in the dialog. - /// @param buttons A list of the button specifications. - /// @param pic The icon to show at the top left. - /// @param t The type of the icon. - /// @param parent Optionally, a parent dialog. - cThreeChoice(std::vector& strings, std::array& buttons, pic_num_t pic, ePicType t, cDialog* parent = nullptr); - /// Create a dialog with up to three buttons. - /// @param strings A list of the strings to place in the dialog. - /// @param buttons A list of the index of the button; this is an index into available_btns which is in turn used to index basic_buttons. - /// @param pic The icon to show at the top left. - /// @param t The type of the icon. - /// @param parent Optionally, a parent dialog. - cThreeChoice(std::vector& strings, std::array& buttons, pic_num_t pic, ePicType t, cDialog* parent = nullptr); - /// @copydoc cChoiceDlog::show() - /// @note The unique key in this case is the label specified in the button specification. - std::string show(); -}; - -/// A dialog that presents a list of strings with LEDs and allows you to choose one. -/// The list may span several pages. -class cStringChoice { - static const size_t per_page = 40; - cDialog dlg; - bool onLeft(); - bool onRight(); - bool onCancel(cDialog& me); - bool onOkay(cDialog& me); - bool onSelect(bool losing); - void attachHandlers(); - void fillPage(); - std::vector strings; - size_t page, cur; - cLedGroup* leds; - std::function select_handler; -public: - /// Initializes a dialog from a list of strings. - /// @param strs A list of all strings in the dialog. - /// @param title The title to show in the dialog. - /// @param parent Optionally, a parent dialog. - explicit cStringChoice(std::vector& strs, std::string title, cDialog* parent = nullptr); - /// Initializes a dialog from an iterator pair. - /// @param begin An iterator to the first string in the dialog. - /// @param end An iterator to one past the last string in the dialog. - /// @param title The title to show in the dialog. - /// @param parent Optionally, a parent dialog. - /// @note Currently, only vector iterators are supported. - cStringChoice(std::vector::iterator begin, std::vector::iterator end, std::string title, cDialog* parent = nullptr); - /// Attach a handler to be called when the selected item changes. - /// @param f A function that takes a reference to the dialog and the index of the newly selected item. - void attachSelectHandler(std::function f); - /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. - /// @return A pointer to the dialog. - cDialog* operator->(); - /// Show the dialog. - /// @param selectedIndex The index of the string that should be initially selected when the dialog is shown. - /// @return The index of the newly selected string; if the user cancelled, this will be equal to selectedIndex. - /// If initialized from an iterator range, this will be relative to begin. - size_t show(size_t selectedIndex); -}; - -/// Like cStringChoice, but presents a list of icons rather than strings. -class cPictChoice { - static const size_t per_page = 36; - bool didAccept; - cDialog dlg; - void attachHandlers(); - bool onLeft(); - bool onRight(); - bool onCancel(); - bool onOkay(); - bool onSelect(bool losing); - void fillPage(); - std::vector> picts; - size_t page, cur; - cLedGroup* leds; - std::function select_handler; -public: - /// Initializes a dialog from a list of icons. - /// @param pics A list of all icons in the dialog. - /// @param t The type of icons to show; all icons are assumed to be of the same type. - /// @param parent Optionally, a parent dialog. - cPictChoice(const std::vector& pics, ePicType t, cDialog* parent = nullptr); - /// Initializes a dialog from a list of icons. - /// @param pics A list of all icons in the dialog as {num,type} pairs. - /// @param parent Optionally, a parent dialog. - cPictChoice(const std::vector>& pics, cDialog* parent = nullptr); - /// Initializes a dialog from an iterator pair. - /// @param begin An iterator to the first icon in the dialog. - /// @param end An iterator to one past the last icon in the dialog. - /// @param t The type of icons to show; all icons are assumed to be of the same type. - /// @param parent Optionally, a parent dialog. - cPictChoice(std::vector::const_iterator begin, std::vector::const_iterator end, ePicType t, cDialog* parent = nullptr); - /// Initializes a dialog from an index pair. - /// @param first The number of the first icon in the dialog. - /// @param last The number of the last icon in the dialog. - /// @param t The type of icons to show; all icons are assumed to be of the same type. - /// @param parent Optionally, a parent dialog. - cPictChoice(pic_num_t first, pic_num_t last, ePicType t, cDialog* parent = nullptr); - /// Attach a handler to be called when the selected item changes. - /// @param f A function that takes a reference to the dialog and the index of the newly selected item. - void attachSelectHandler(std::function f); - /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. - /// @return A pointer to the dialog. - cDialog* operator->(); - /// Show the dialog. - /// @param cur_sel The index of the icon that should be initially selected when the dialog is shown. - /// @return false if the user clicked Cancel, true otherwise. - bool show(size_t cur_sel); - /// Get the chosen icon. - /// @return The number of the chosen icon. - pic_num_t getPicChosen(); - /// Get the chosen icon. - /// @return The type of the chosen icon. - ePicType getPicChosenType(); - /// Get the index of the selected icon in the original list. - /// @return The index - size_t getSelected(); -}; -#endif - -/// Shows a simple error dialog for an unrecoverable condition. -/// @param str1 The first string in the error dialog. -/// @param str2 The second string in the error dialog. -/// @param parent Optionally, a parent dialog. -void showFatalError(std::string str1, std::string str2, cDialog* parent = nullptr); -/// Shows a simple error dialog for an unrecoverable condition. -/// @param str1 The string in the error dialog. -/// @param parent Optionally, a parent dialog. -void showFatalError(std::string str1, cDialog* parent = nullptr); - -/// Shows a simple error dialog for a recoverable condition. -/// @param str1 The first string in the error dialog. -/// @param str2 The second string in the error dialog. -/// @param parent Optionally, a parent dialog. -void showError(std::string str1, std::string str2, cDialog* parent = nullptr); -/// Shows a simple error dialog for a recoverable condition. -/// @param str1 The string in the error dialog. -/// @param parent Optionally, a parent dialog. -void showError(std::string str1, cDialog* parent = nullptr); - -/// Shows a simple warning message dialog. -/// @param str1 The first string in the warning dialog. -/// @param str2 The second string in the warning dialog. -/// @param parent Optionally, a parent dialog. -void showWarning(std::string str1, std::string str2, cDialog* parent = nullptr); -/// Shows a simple warning message dialog. -/// @param str1 The string in the warning dialog. -/// @param parent Optionally, a parent dialog. -void showWarning(std::string str1, cDialog* parent = nullptr); diff --git a/src/dialogxml/field.cpp b/src/dialogxml/field.cpp index 51e62ef9..411b3580 100644 --- a/src/dialogxml/field.cpp +++ b/src/dialogxml/field.cpp @@ -12,7 +12,7 @@ #include #include #include "dialog.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "graphtool.hpp" #include "winutil.hpp" #include "cursors.hpp" diff --git a/src/dialogxml/pictchoice.cpp b/src/dialogxml/pictchoice.cpp new file mode 100644 index 00000000..7d94d57a --- /dev/null +++ b/src/dialogxml/pictchoice.cpp @@ -0,0 +1,154 @@ +/* + * dlogutil.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include "pictchoice.hpp" + +#include +#include +#include "pict.hpp" + +cPictChoice::cPictChoice(const std::vector& pics,ePicType t,cDialog* parent) : cPictChoice(pics.begin(), pics.end(), t, parent) {} + +cPictChoice::cPictChoice(const std::vector>& pics,cDialog* parent) : dlg("choose-pict",parent) { + picts = pics; + attachHandlers(); +} + +cPictChoice::cPictChoice( + std::vector::const_iterator begin, + std::vector::const_iterator end, + ePicType t, + cDialog* parent + ) : dlg("choose-pict",parent) { + for(auto iter = begin; iter != end; iter++) { + picts.push_back({*iter,t}); + } + attachHandlers(); +} + +cPictChoice::cPictChoice(pic_num_t first, pic_num_t last, ePicType t, cDialog* parent) : dlg("choose-pict",parent) { + for(pic_num_t i = first; i <= last; i++) { + picts.push_back({i,t}); + } + attachHandlers(); +} + +void cPictChoice::attachHandlers() { + using namespace std::placeholders; + dlg["left"].attachClickHandler(std::bind(&cPictChoice::onLeft,this)); + dlg["right"].attachClickHandler(std::bind(&cPictChoice::onRight,this)); + dlg["done"].attachClickHandler(std::bind(&cPictChoice::onOkay,this)); + dlg["cancel"].attachClickHandler(std::bind(&cPictChoice::onCancel,this)); + leds = &dynamic_cast(dlg["group"]); + leds->attachFocusHandler(std::bind(&cPictChoice::onSelect,this,_3)); + if(picts.size() <= per_page) { + dlg["left"].hide(); + dlg["right"].hide(); + } +} + +cDialog* cPictChoice::operator->() { + return &dlg; +} + +bool cPictChoice::show(size_t cur_sel){ + if(cur_sel >= picts.size()) + cur_sel = 0; + cur = cur_sel; + dlg.setResult(picts[cur_sel]); + page = cur / per_page; + fillPage(); + dlg.run(); + return didAccept; +} + +void cPictChoice::attachSelectHandler(std::function f) { + select_handler = f; +} + +void cPictChoice::fillPage(){ + cLedGroup& group = dynamic_cast(dlg["group"]); + group.setSelected(""); // unselect all LEDs, since the currently selected one may be on another page + for(size_t i = 0; i < per_page; i++){ + std::ostringstream sout; + sout << "led" << i + 1; + if(page * per_page + i >= picts.size()) + dlg[sout.str()].hide(); + else + dlg[sout.str()].show(); + if(page * per_page + i == cur) + group.setSelected(sout.str()); + sout.str(""); + sout << "pic" << i + 1; + cPict& pic = dynamic_cast(dlg[sout.str()]); + if(page * per_page + i < picts.size()){ + pic.show(); + ePicType tp = picts[per_page * page + i].second; + pic.setPict(picts[per_page * page + i].first, tp); + rectangle b = pic.getBounds(); + if(tp == PIC_DLOG_LG || tp == PIC_CUSTOM_DLOG_LG || tp == PIC_SCEN_LG) { + pic.setFormat(TXT_WRAP, false); + b.width() /= 2; + b.height() /= 2; + } else if(tp == PIC_FULL) { + pic.setFormat(TXT_WRAP, false); + b.width() = 40; + b.height() = 40; + } else pic.setFormat(TXT_WRAP, true); + pic.setBounds(b); + }else pic.hide(); + } +} + +bool cPictChoice::onLeft(){ + if(page == 0) page = (picts.size() - 1) / per_page; + else page--; + fillPage(); + return true; +} + +bool cPictChoice::onRight(){ + if(page == (picts.size() - 1) / per_page) page = 0; + else page++; + fillPage(); + return true; +} + +bool cPictChoice::onCancel(){ + dlg.toast(false); + didAccept = false; + return true; +} + +bool cPictChoice::onOkay(){ + dlg.setResult(picts[cur]); + dlg.toast(true); + didAccept = true; + return true; +} + +bool cPictChoice::onSelect(bool losing) { + if(losing) return true; + int i = boost::lexical_cast(leds->getSelected().substr(3)); + cur = page * per_page + i - 1; + if(select_handler) + select_handler(*this, cur); + return true; +} + +pic_num_t cPictChoice::getPicChosen() { + return dlg.getResult>().first; +} + +ePicType cPictChoice::getPicChosenType() { + return dlg.getResult>().second; +} + +size_t cPictChoice::getSelected() { + return cur; +} diff --git a/src/dialogxml/pictchoice.hpp b/src/dialogxml/pictchoice.hpp new file mode 100644 index 00000000..e9567cd8 --- /dev/null +++ b/src/dialogxml/pictchoice.hpp @@ -0,0 +1,80 @@ +/* + * dlogutil.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef DIALOG_PICTCHOICE_H +#define DIALOG_PICTCHOICE_H + +#include +#include +#include + +#include "dialog.hpp" +#include "button.hpp" +#include "pictypes.hpp" + +/// A dialog that presents a list of icons with LEDs and allows you to choose one. +/// The list may span several pages. +class cPictChoice { + static const size_t per_page = 36; + bool didAccept; + cDialog dlg; + void attachHandlers(); + bool onLeft(); + bool onRight(); + bool onCancel(); + bool onOkay(); + bool onSelect(bool losing); + void fillPage(); + std::vector> picts; + size_t page, cur; + cLedGroup* leds; + std::function select_handler; +public: + /// Initializes a dialog from a list of icons. + /// @param pics A list of all icons in the dialog. + /// @param t The type of icons to show; all icons are assumed to be of the same type. + /// @param parent Optionally, a parent dialog. + cPictChoice(const std::vector& pics, ePicType t, cDialog* parent = nullptr); + /// Initializes a dialog from a list of icons. + /// @param pics A list of all icons in the dialog as {num,type} pairs. + /// @param parent Optionally, a parent dialog. + cPictChoice(const std::vector>& pics, cDialog* parent = nullptr); + /// Initializes a dialog from an iterator pair. + /// @param begin An iterator to the first icon in the dialog. + /// @param end An iterator to one past the last icon in the dialog. + /// @param t The type of icons to show; all icons are assumed to be of the same type. + /// @param parent Optionally, a parent dialog. + cPictChoice(std::vector::const_iterator begin, std::vector::const_iterator end, ePicType t, cDialog* parent = nullptr); + /// Initializes a dialog from an index pair. + /// @param first The number of the first icon in the dialog. + /// @param last The number of the last icon in the dialog. + /// @param t The type of icons to show; all icons are assumed to be of the same type. + /// @param parent Optionally, a parent dialog. + cPictChoice(pic_num_t first, pic_num_t last, ePicType t, cDialog* parent = nullptr); + /// Attach a handler to be called when the selected item changes. + /// @param f A function that takes a reference to the dialog and the index of the newly selected item. + void attachSelectHandler(std::function f); + /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. + /// @return A pointer to the dialog. + cDialog* operator->(); + /// Show the dialog. + /// @param cur_sel The index of the icon that should be initially selected when the dialog is shown. + /// @return false if the user clicked Cancel, true otherwise. + bool show(size_t cur_sel); + /// Get the chosen icon. + /// @return The number of the chosen icon. + pic_num_t getPicChosen(); + /// Get the chosen icon. + /// @return The type of the chosen icon. + ePicType getPicChosenType(); + /// Get the index of the selected icon in the original list. + /// @return The index + size_t getSelected(); +}; + +#endif diff --git a/src/dialogxml/strchoice.cpp b/src/dialogxml/strchoice.cpp new file mode 100644 index 00000000..068b4c5d --- /dev/null +++ b/src/dialogxml/strchoice.cpp @@ -0,0 +1,120 @@ +/* + * dlogutil.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include "strchoice.hpp" + +#include +#include + +#include + +cStringChoice::cStringChoice( + std::vector& strs, + std::string title, + cDialog* parent + ) : dlg("choose-string",parent) { + if(!title.empty()) dlg["title"].setText(title); + strings = strs; + attachHandlers(); +} + +cStringChoice::cStringChoice( + std::vector::iterator begin, + std::vector::iterator end, + std::string title, + cDialog* parent + ) : dlg("choose-string",parent) { + if(!title.empty()) dlg["title"].setText(title); + copy(begin,end,std::inserter(strings, strings.begin())); + attachHandlers(); +} + +void cStringChoice::attachHandlers() { + using namespace std::placeholders; + dlg["left"].attachClickHandler(std::bind(&cStringChoice::onLeft,this)); + dlg["right"].attachClickHandler(std::bind(&cStringChoice::onRight,this)); + dlg["done"].attachClickHandler(std::bind(&cStringChoice::onOkay,this,_1)); + dlg["cancel"].attachClickHandler(std::bind(&cStringChoice::onCancel,this,_1)); + leds = &dynamic_cast(dlg["strings"]); + leds->attachFocusHandler(std::bind(&cStringChoice::onSelect,this,_3)); + if(strings.size() <= per_page) { + dlg["left"].hide(); + dlg["right"].hide(); + } +} + +cDialog* cStringChoice::operator->() { + return &dlg; +} + +size_t cStringChoice::show(size_t selectedIndex) { + cur = selectedIndex; + if(cur >= strings.size()) cur = 0; + page = cur / per_page; + fillPage(); + dlg.setResult(selectedIndex); + dlg.run(); + return dlg.getResult(); +} + +void cStringChoice::attachSelectHandler(std::function f) { + select_handler = f; +} + +void cStringChoice::fillPage(){ + cLedGroup& group = dynamic_cast(dlg["strings"]); + group.setSelected(""); // unselect all LEDs, since the currently selected one may be on another page + for(unsigned int i = 0; i < per_page; i++){ + std::ostringstream sout; + sout << "led" << i + 1; + if(page * per_page + i >= strings.size()){ + dlg[sout.str()].hide(); + continue; + }else + dlg[sout.str()].show(); + if(page * per_page + i == cur) + group.setSelected(sout.str()); + if(page * per_page + i < strings.size()){ + dlg[sout.str()].setText(strings[per_page * page + i]); + } + } +} + +bool cStringChoice::onLeft(){ + if(page == 0) page = strings.size() / per_page; + else page--; + fillPage(); + return true; +} + +bool cStringChoice::onRight(){ + if(page == strings.size() / per_page) page = 0; + else page++; + fillPage(); + return true; +} + +bool cStringChoice::onCancel(cDialog& me){ + me.toast(false); + return true; +} + +bool cStringChoice::onOkay(cDialog& me){ + dlg.setResult(cur); + me.toast(true); + return true; +} + +bool cStringChoice::onSelect(bool losing) { + if(losing) return true; + int i = boost::lexical_cast(leds->getSelected().substr(3)); + cur = page * per_page + i - 1; + if(select_handler) + select_handler(*this, cur); + return true; +} diff --git a/src/dialogxml/strchoice.hpp b/src/dialogxml/strchoice.hpp new file mode 100644 index 00000000..143d8e62 --- /dev/null +++ b/src/dialogxml/strchoice.hpp @@ -0,0 +1,60 @@ +/* + * dlogutil.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef DIALOG_STRINGCHOICE_H +#define DIALOG_STRINGCHOICE_H + +#include +#include +#include +#include "dialog.hpp" +#include "button.hpp" + +/// A dialog that presents a list of strings with LEDs and allows you to choose one. +/// The list may span several pages. +class cStringChoice { + static const size_t per_page = 40; + cDialog dlg; + bool onLeft(); + bool onRight(); + bool onCancel(cDialog& me); + bool onOkay(cDialog& me); + bool onSelect(bool losing); + void attachHandlers(); + void fillPage(); + std::vector strings; + size_t page, cur; + cLedGroup* leds; + std::function select_handler; +public: + /// Initializes a dialog from a list of strings. + /// @param strs A list of all strings in the dialog. + /// @param title The title to show in the dialog. + /// @param parent Optionally, a parent dialog. + explicit cStringChoice(std::vector& strs, std::string title, cDialog* parent = nullptr); + /// Initializes a dialog from an iterator pair. + /// @param begin An iterator to the first string in the dialog. + /// @param end An iterator to one past the last string in the dialog. + /// @param title The title to show in the dialog. + /// @param parent Optionally, a parent dialog. + /// @note Currently, only vector iterators are supported. + cStringChoice(std::vector::iterator begin, std::vector::iterator end, std::string title, cDialog* parent = nullptr); + /// Attach a handler to be called when the selected item changes. + /// @param f A function that takes a reference to the dialog and the index of the newly selected item. + void attachSelectHandler(std::function f); + /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. + /// @return A pointer to the dialog. + cDialog* operator->(); + /// Show the dialog. + /// @param selectedIndex The index of the string that should be initially selected when the dialog is shown. + /// @return The index of the newly selected string; if the user cancelled, this will be equal to selectedIndex. + /// If initialized from an iterator range, this will be relative to begin. + size_t show(size_t selectedIndex); +}; + +#endif diff --git a/src/dialogxml/strdlog.cpp b/src/dialogxml/strdlog.cpp new file mode 100644 index 00000000..2d70ab90 --- /dev/null +++ b/src/dialogxml/strdlog.cpp @@ -0,0 +1,115 @@ +/* + * dlogutil.cpp + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#include "strdlog.hpp" + +#include +#include "winutil.hpp" +#include "pict.hpp" + +std::string cStrDlog::getFileName(short n_strs, ePicType type, bool hasTitle){ + std::ostringstream sout; + sout << n_strs << "str"; + if(hasTitle) sout << "-title"; + if(type == PIC_DLOG_LG || type == PIC_CUSTOM_DLOG_LG || type == PIC_SCEN_LG) + sout << "-lg"; + return sout.str(); +} + +cStrDlog::cStrDlog(std::string str1,std::string str2,std::string title,pic_num_t pic,ePicType t,cDialog* parent) + : dlg(cStrDlog::getFileName((str1 != "") + (str2 != ""), t, title != ""), parent), type(t) { + using namespace std::placeholders; + cPict& pic_ctrl = dynamic_cast(dlg["pict"]); + pic_ctrl.setPict(pic, type); + if(str1 != "") { + dlg["str1"].setText(str1); + if(str2 != "") dlg["str2"].setText(str2); + }else if(str2 != "") dlg["str1"].setText(str2); + if(title != "") dlg["title"].setText(title); + dlg["record"].hide(); + dlg["record"].attachClickHandler(std::bind(&cStrDlog::onRecord, this, _2)); + dlg["done"].attachClickHandler(std::bind(&cStrDlog::onDismiss, this)); +} + +bool cStrDlog::onRecord(std::string id){ + if(hasRecord) rec_f(dlg); + else dlg[id].hide(); + return hasRecord; +} + +bool cStrDlog::onDismiss(){ + dlg.toast(true); + return true; +} + +cStrDlog& cStrDlog::setSound(snd_num_t snd){ + sound = snd; + return *this; +} + +cStrDlog& cStrDlog::setRecordHandler(record_callback_t rec){ + if(rec == nullptr){ + hasRecord = false; + dlg["record"].hide(); + }else{ + hasRecord = true; + rec_f = rec; + dlg["record"].show(); + } + return *this; +} + +cDialog* cStrDlog::operator->() { + return &dlg; +} + +void cStrDlog::show(){ + if(sound > 0) play_sound(sound); + dlg.run(); +} + +static void giveError(pic_num_t pic, std::string title, std::string str1, std::string str2, cDialog* parent) { + cStrDlog error(str1,str2,title,pic,PIC_DLOG,parent); + error->getControl("record").setText("Copy"); + error.setRecordHandler([](cDialog& me) { + std::string error = me["str1"].getText(); + try { + std::string error2 = me["str2"].getText(); + error += "\n\n" + error2; + } catch(std::invalid_argument) {} + for(char& c : error) { + if(c == '|') c = '\n'; + } + set_clipboard(error); + }); + error.show(); +} + +void showError(std::string str1, cDialog* parent) { + showError(str1, "", parent); +} + +void showError(std::string str1, std::string str2, cDialog* parent) { + giveError(25, "Error", str1, str2, parent); +} + +void showWarning(std::string str1, cDialog* parent) { + showWarning(str1, "", parent); +} + +void showWarning(std::string str1, std::string str2, cDialog* parent) { + giveError(24, "Warning", str1, str2, parent); +} + +void showFatalError(std::string str1, cDialog* parent) { + showFatalError(str1, "", parent); +} + +void showFatalError(std::string str1, std::string str2, cDialog* parent) { + giveError(25, "Error!!!", str1, str2, parent); +} diff --git a/src/dialogxml/strdlog.hpp b/src/dialogxml/strdlog.hpp new file mode 100644 index 00000000..5bffd8ce --- /dev/null +++ b/src/dialogxml/strdlog.hpp @@ -0,0 +1,90 @@ +/* + * dlogutil.h + * BoE + * + * Created by Celtic Minstrel on 11/05/09. + * + */ + +#ifndef DIALOG_2STRING_H +#define DIALOG_2STRING_H + +#include +#include +#include "pictypes.hpp" +#include "soundtool.hpp" // for snd_num_t +#include "dialog.hpp" + +/// The signature of a record handler for cStrDlog. +typedef std::function record_callback_t; + +/// A simple dialog with one or two long strings, an optional title, and an optional record button. +class cStrDlog { + static std::string getFileName(short n_strs, ePicType type, bool hasTitle); + cDialog dlg; + short sound = -1; + record_callback_t rec_f; + bool hasRecord; + const ePicType type; + bool onRecord(std::string id); + bool onDismiss(); +public: + /// Construct a string dialog. + /// @param str1 The first string. + /// @param str2 The second string. If left as an empty string, there will be only one string in the dialog. + /// @param title The title. If left as an empty string, there will be no title. + /// @param pic The icon to show at the top left. + /// @param t The type of icon to show. + /// @param parent Optionally, a parent dialog. + cStrDlog(std::string str1,std::string str2,std::string title,pic_num_t pic,ePicType t,cDialog* parent = nullptr); + /// Set a sound to be played when the dialog is shown. + /// @param num The sound number. + /// @return This object, for method-call chaining. + cStrDlog& setSound(snd_num_t num); + /// Set a record handler. + /// @param rec The handler. + /// @return This object, for method-call chaining. + /// @note Only one record handler can be set at a time. To remove it, set it to null. + /// @note The presence of the Record button is determined entirely by the presence of a record handler. + /// + /// A record handler should take one parameter, which is a reference to the dialog. + /// (That's the cDialog, not the cStrDlog.) It should return void. + cStrDlog& setRecordHandler(record_callback_t rec); + /// Reference the cDialog powering this choice dialog, perhaps to customize details of it. + /// @return A pointer to the dialog. + cDialog* operator->(); + /// Show the dialog. + void show(); +}; + +/// Shows a simple error dialog for an unrecoverable condition. +/// @param str1 The first string in the error dialog. +/// @param str2 The second string in the error dialog. +/// @param parent Optionally, a parent dialog. +void showFatalError(std::string str1, std::string str2, cDialog* parent = nullptr); +/// Shows a simple error dialog for an unrecoverable condition. +/// @param str1 The string in the error dialog. +/// @param parent Optionally, a parent dialog. +void showFatalError(std::string str1, cDialog* parent = nullptr); + +/// Shows a simple error dialog for a recoverable condition. +/// @param str1 The first string in the error dialog. +/// @param str2 The second string in the error dialog. +/// @param parent Optionally, a parent dialog. +void showError(std::string str1, std::string str2, cDialog* parent = nullptr); +/// Shows a simple error dialog for a recoverable condition. +/// @param str1 The string in the error dialog. +/// @param parent Optionally, a parent dialog. +void showError(std::string str1, cDialog* parent = nullptr); + +/// Shows a simple warning message dialog. +/// @param str1 The first string in the warning dialog. +/// @param str2 The second string in the warning dialog. +/// @param parent Optionally, a parent dialog. +void showWarning(std::string str1, std::string str2, cDialog* parent = nullptr); +/// Shows a simple warning message dialog. +/// @param str1 The string in the warning dialog. +/// @param parent Optionally, a parent dialog. +void showWarning(std::string str1, cDialog* parent = nullptr); + +#endif diff --git a/src/pcedit/pc.action.cpp b/src/pcedit/pc.action.cpp index a5d39356..51ffa1a0 100644 --- a/src/pcedit/pc.action.cpp +++ b/src/pcedit/pc.action.cpp @@ -10,7 +10,8 @@ #include "graphtool.hpp" #include "soundtool.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" +#include "dialog.hpp" +#include "control.hpp" #include extern cUniverse univ; diff --git a/src/pcedit/pc.editors.cpp b/src/pcedit/pc.editors.cpp index 0baf2da5..cbccc94d 100644 --- a/src/pcedit/pc.editors.cpp +++ b/src/pcedit/pc.editors.cpp @@ -7,7 +7,9 @@ #include "dialog.hpp" #include "control.hpp" #include "button.hpp" -#include "dlogutil.hpp" +#include "pict.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "winutil.hpp" #include diff --git a/src/pcedit/pc.fileio.cpp b/src/pcedit/pc.fileio.cpp index 570c63c1..132efac3 100644 --- a/src/pcedit/pc.fileio.cpp +++ b/src/pcedit/pc.fileio.cpp @@ -10,7 +10,6 @@ #include "soundtool.hpp" #include "pc.editors.hpp" #include "mathutil.hpp" -#include "dlogutil.hpp" #include "restypes.hpp" #include "fileio.hpp" diff --git a/src/pcedit/pc.graphics.cpp b/src/pcedit/pc.graphics.cpp index 19aa28cf..cff04937 100644 --- a/src/pcedit/pc.graphics.cpp +++ b/src/pcedit/pc.graphics.cpp @@ -7,7 +7,6 @@ #include "pc.action.hpp" #include "soundtool.hpp" #include "graphtool.hpp" -#include "dlogutil.hpp" #include "restypes.hpp" #include "message.hpp" #include "mathutil.hpp" diff --git a/src/pcedit/pc.main.cpp b/src/pcedit/pc.main.cpp index 4d7cab78..1420c0d3 100644 --- a/src/pcedit/pc.main.cpp +++ b/src/pcedit/pc.main.cpp @@ -11,7 +11,10 @@ #include "soundtool.hpp" #include "graphtool.hpp" #include "boe.consts.hpp" -#include "dlogutil.hpp" +#include "dialog.hpp" +#include "control.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "fileio.hpp" #include "pc.menus.hpp" #include "winutil.hpp" diff --git a/src/scenedit/scen.actions.cpp b/src/scenedit/scen.actions.cpp index 5b7a90bd..19628ea8 100644 --- a/src/scenedit/scen.actions.cpp +++ b/src/scenedit/scen.actions.cpp @@ -21,7 +21,8 @@ #include "winutil.hpp" #include "cursors.hpp" #include "scrollbar.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "gitrev.hpp" #include "scen.btnmg.hpp" diff --git a/src/scenedit/scen.core.cpp b/src/scenedit/scen.core.cpp index 24f2b7cb..09f5f9d7 100644 --- a/src/scenedit/scen.core.cpp +++ b/src/scenedit/scen.core.cpp @@ -18,7 +18,11 @@ #include "scen.actions.hpp" #include "scen.menus.hpp" #include "dialog.hpp" -#include "dlogutil.hpp" +#include "control.hpp" +#include "button.hpp" +#include "strdlog.hpp" +#include "3choice.hpp" +#include "strchoice.hpp" #include "fileio.hpp" #include "field.hpp" #include "restypes.hpp" diff --git a/src/scenedit/scen.fileio.cpp b/src/scenedit/scen.fileio.cpp index 83d3d55b..11f08651 100644 --- a/src/scenedit/scen.fileio.cpp +++ b/src/scenedit/scen.fileio.cpp @@ -14,7 +14,6 @@ #include "mathutil.hpp" #include "oldstructs.hpp" #include "fileio.hpp" -#include "dlogutil.hpp" #include "tarball.hpp" #include "gzstream.h" #include "tinyprint.h" diff --git a/src/scenedit/scen.keydlgs.cpp b/src/scenedit/scen.keydlgs.cpp index 49d0c85f..43d4cdb5 100644 --- a/src/scenedit/scen.keydlgs.cpp +++ b/src/scenedit/scen.keydlgs.cpp @@ -10,7 +10,13 @@ #include "scen.graphics.hpp" #include "scen.keydlgs.hpp" #include "scen.core.hpp" -#include "dlogutil.hpp" +#include "dialog.hpp" +#include "control.hpp" +#include "button.hpp" +#include "strdlog.hpp" +#include "3choice.hpp" +#include "strchoice.hpp" +#include "pictchoice.hpp" #include "restypes.hpp" #include "spell.hpp" diff --git a/src/scenedit/scen.main.cpp b/src/scenedit/scen.main.cpp index b2518555..ec2e6983 100644 --- a/src/scenedit/scen.main.cpp +++ b/src/scenedit/scen.main.cpp @@ -20,7 +20,8 @@ #include "scrollbar.hpp" #include "winutil.hpp" #include "cursors.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "scen.menus.hpp" #include "restypes.hpp" diff --git a/src/scenedit/scen.townout.cpp b/src/scenedit/scen.townout.cpp index e88574a7..28e68caf 100644 --- a/src/scenedit/scen.townout.cpp +++ b/src/scenedit/scen.townout.cpp @@ -14,7 +14,8 @@ #include "scen.core.hpp" #include "mathutil.hpp" #include "button.hpp" -#include "dlogutil.hpp" +#include "strdlog.hpp" +#include "choicedlog.hpp" #include "winutil.hpp" #include "stack.hpp" #include "scrollpane.hpp" diff --git a/src/tools/fileio_party.cpp b/src/tools/fileio_party.cpp index ee67609d..5a8b6b8d 100644 --- a/src/tools/fileio_party.cpp +++ b/src/tools/fileio_party.cpp @@ -11,7 +11,7 @@ #include #include -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "gzstream.h" #include "universe.hpp" diff --git a/src/tools/fileio_scen.cpp b/src/tools/fileio_scen.cpp index 9dac10a7..9a2c687f 100644 --- a/src/tools/fileio_scen.cpp +++ b/src/tools/fileio_scen.cpp @@ -12,7 +12,7 @@ #include #include -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "scenario.hpp" #include "regtown.hpp" diff --git a/src/tools/qdpict.mac.cpp b/src/tools/qdpict.mac.cpp index fcb8d3a6..f474da6d 100644 --- a/src/tools/qdpict.mac.cpp +++ b/src/tools/qdpict.mac.cpp @@ -15,11 +15,14 @@ #include #include +#include -#include "dlogutil.hpp" +#include "strdlog.hpp" #include "porting.hpp" #include "location.hpp" +namespace fs = boost::filesystem; + static int16_t extract_word(char* ptr) { int16_t s = *(int16_t*) ptr; flip_short(&s);