New dialog presents a yes/no choice with alternate non-exclusive actions
This commit is contained in:
111
src/dialogxml/dialogs/btnpanel.cpp
Normal file
111
src/dialogxml/dialogs/btnpanel.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#include "btnpanel.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include "dialogxml/widgets/field.hpp"
|
||||
#include "dialogxml/dialogs/strdlog.hpp"
|
||||
#include "fileio/resmgr/res_dialog.hpp"
|
||||
#include "sounds.hpp"
|
||||
#include "gfx/render_shapes.hpp"
|
||||
#include "tools/cursors.hpp"
|
||||
|
||||
cButtonPanel::cButtonPanel(cDialog* parent)
|
||||
: dlg(*ResMgr::dialogs.get("tiny-button-panel"), parent)
|
||||
{}
|
||||
|
||||
cButtonPanel::cButtonPanel(const std::vector<std::string>& strs, std::vector<std::function<void(cButtonPanel&)>> click_handlers, std::string title, std::string ok_str, cDialog* parent)
|
||||
: cButtonPanel(parent)
|
||||
{
|
||||
setTitle(title);
|
||||
if(!ok_str.empty()){
|
||||
dlg["done"].setText(ok_str);
|
||||
}
|
||||
strings = strs;
|
||||
this->click_handlers = click_handlers;
|
||||
attachHandlers();
|
||||
}
|
||||
|
||||
void cButtonPanel::attachHandlers() {
|
||||
using namespace std::placeholders;
|
||||
dlg["left"].attachClickHandler(std::bind(&cButtonPanel::onLeft,this));
|
||||
dlg["right"].attachClickHandler(std::bind(&cButtonPanel::onRight,this));
|
||||
dlg["done"].attachClickHandler(std::bind(&cButtonPanel::onOkay,this,_1));
|
||||
dlg["cancel"].attachClickHandler(std::bind(&cButtonPanel::onCancel,this,_1));
|
||||
if(strings.size() <= per_page) {
|
||||
dlg["left"].hide();
|
||||
dlg["right"].hide();
|
||||
}
|
||||
// Attach click handler to the tiny buttons
|
||||
for(int i = 0; i < per_page; ++i){
|
||||
short string_idx = page * per_page + i;
|
||||
std::ostringstream sout;
|
||||
sout << "button" << i + 1;
|
||||
dlg[sout.str()].attachClickHandler([i, this](cDialog&,std::string,eKeyMod) -> bool {
|
||||
click_handlers[i](*this);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
cDialog* cButtonPanel::operator->() {
|
||||
return &dlg;
|
||||
}
|
||||
|
||||
bool cButtonPanel::show() {
|
||||
page = 0;
|
||||
dlg.run(std::bind(&cButtonPanel::fillPage, this));
|
||||
return dlg.getResult<bool>();
|
||||
}
|
||||
|
||||
void cButtonPanel::fillPage(){
|
||||
for(unsigned int i = 0; i < per_page; i++){
|
||||
short string_idx = page * per_page + i;
|
||||
std::ostringstream sout;
|
||||
sout << "button" << i + 1;
|
||||
if(string_idx < strings.size()){
|
||||
dlg[sout.str()].setText(strings[string_idx]);
|
||||
dlg[sout.str()].recalcRect();
|
||||
dlg[sout.str()].show();
|
||||
}else{
|
||||
dlg[sout.str()].hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cButtonPanel::onLeft(){
|
||||
if(page == 0) page = lastPage();
|
||||
else page--;
|
||||
fillPage();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cButtonPanel::onRight(){
|
||||
if(page == lastPage()) page = 0;
|
||||
else page++;
|
||||
fillPage();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cButtonPanel::onCancel(cDialog& me){
|
||||
dlg.setResult(false);
|
||||
me.toast(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cButtonPanel::onOkay(cDialog& me){
|
||||
dlg.setResult(true);
|
||||
me.toast(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cButtonPanel::setTitle(const std::string &title) {
|
||||
if(!title.empty()) dlg["title"].setText(title);
|
||||
}
|
||||
|
||||
size_t cButtonPanel::lastPage() const {
|
||||
return (strings.size() - 1) / per_page;
|
||||
}
|
47
src/dialogxml/dialogs/btnpanel.hpp
Normal file
47
src/dialogxml/dialogs/btnpanel.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef DIALOG_BTNPANEL_H
|
||||
#define DIALOG_BTNPANEL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <boost/optional.hpp>
|
||||
#include "dialog.hpp"
|
||||
#include "dialogxml/widgets/ledgroup.hpp"
|
||||
|
||||
/// A dialog that presents a list of labeled tiny buttons, plus an OK and Cancel button.
|
||||
/// The list may span several pages.
|
||||
class cButtonPanel {
|
||||
const size_t per_page = 5;
|
||||
cDialog dlg;
|
||||
bool onLeft();
|
||||
bool onRight();
|
||||
bool onCancel(cDialog& me);
|
||||
bool onOkay(cDialog& me);
|
||||
void attachHandlers();
|
||||
void fillPage();
|
||||
size_t lastPage() const;
|
||||
std::vector<std::string> strings;
|
||||
std::vector<std::function<void(cButtonPanel&)>> click_handlers;
|
||||
size_t page, cur;
|
||||
cButtonPanel(cDialog* parent);
|
||||
public:
|
||||
/// Initializes a dialog from a list of strings.
|
||||
/// @param strs A list of all strings in the dialog.
|
||||
/// @param click_handlers A list of click handlers for the strings
|
||||
/// @param title The title to show in the dialog.
|
||||
/// @param parent Optionally, a parent dialog.
|
||||
explicit cButtonPanel(const std::vector<std::string>& strs, std::vector<std::function<void(cButtonPanel&)>> click_handlers, std::string title, std::string ok_str = "", cDialog* parent = 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 True if OK was pressed, false if Cancel pressed
|
||||
bool show();
|
||||
/// Set the dialog's title.
|
||||
/// @param title The new title.
|
||||
void setTitle(const std::string& title);
|
||||
/// Get the list of strings.
|
||||
std::vector<std::string> getStrings() const { return strings; }
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user