Make dialogs iterable

This commit is contained in:
2023-01-07 01:21:42 -05:00
parent 0714004f1c
commit c4d7fc6b99
2 changed files with 57 additions and 0 deletions

View File

@@ -1080,3 +1080,38 @@ bool cDialog::hasControl(std::string id) {
}
const char*const xBadVal::CONTENT = "<content>";
cDialogIterator::cDialogIterator() : parent(nullptr) {}
cDialogIterator::cDialogIterator(cDialog* parent) : parent(parent), current(parent->controls.begin()) {}
std::pair<std::string, cControl*>& cDialogIterator::dereference() const {
// Ugly fugly... especially the reinterpret_cast...
using value_type = std::pair<std::string, cControl*>;
if(children.empty()) return *reinterpret_cast<value_type*>(&*current);
return const_cast<value_type&>(children.front());
}
bool cDialogIterator::equal(const cDialogIterator& other) const {
if(parent == nullptr) return other.parent == nullptr;
return parent == other.parent && current == other.current && std::equal(children.begin(), children.end(), other.children.begin());
}
void cDialogIterator::increment() {
if(children.empty()) {
if(current->second->isContainer()) {
cContainer& box = dynamic_cast<cContainer&>(*current->second);
std::vector<std::pair<std::string, cControl*>> newChildren;
box.forEach([&newChildren](std::string id, cControl& ctrl) {
newChildren.emplace_back(id, &ctrl);
});
children.insert(children.begin(), newChildren.begin(), newChildren.end());
}
++current;
} else {
children.pop_front();
}
if(children.empty() && current == parent->controls.end()) {
parent = nullptr;
}
}

View File

@@ -25,6 +25,7 @@
#include "dialogxml/dialogs/dlogevt.hpp"
#include "location.hpp"
#include <boost/any.hpp>
#include <boost/iterator/iterator_facade.hpp>
class cControl;
class cTextField;
@@ -34,8 +35,23 @@ enum eLabelPos {
LABEL_LEFT, LABEL_ABOVE, LABEL_RIGHT, LABEL_BELOW,
};
class cDialogIterator : public boost::iterator_facade<cDialogIterator, std::pair<std::string, cControl*>, std::forward_iterator_tag> {
friend class boost::iterator_core_access;
cDialog* parent;
std::map<std::string,cControl*>::iterator current;
std::deque<std::pair<std::string, cControl*>> children;
public:
cDialogIterator();
cDialogIterator(cDialog* parent);
protected:
std::pair<std::string, cControl*>& dereference() const;
bool equal(const cDialogIterator& other) const;
void increment();
};
/// Defines a fancy dialog box with various controls.
class cDialog {
friend class cDialogIterator;
typedef std::map<std::string,cControl*>::iterator ctrlIter;
std::map<std::string,cControl*> controls;
short bg;
@@ -213,6 +229,12 @@ public:
}
return p;
}
cDialogIterator begin() {
return cDialogIterator(this);
}
cDialogIterator end() {
return cDialogIterator();
}
cDialog& operator=(cDialog& other) = delete;
cDialog(cDialog& other) = delete;
private: