Refactor allows cLedGroup leds to use relative positioning

This commit is contained in:
2025-03-20 09:35:52 -05:00
parent 1a85fc25ae
commit 341c285a39
2 changed files with 50 additions and 41 deletions

View File

@@ -21,7 +21,7 @@ cLedGroup::cLedGroup(iComponent& parent)
{} {}
cLedGroup::~cLedGroup(){ cLedGroup::~cLedGroup(){
ledIter iter = choices.begin(); ctrlIter iter = choices.begin();
while(iter != choices.end()){ while(iter != choices.end()){
delete iter->second; delete iter->second;
iter++; iter++;
@@ -29,7 +29,7 @@ cLedGroup::~cLedGroup(){
} }
void cLedGroup::recalcRect(){ void cLedGroup::recalcRect(){
ledIter iter = choices.begin(); ctrlIter iter = choices.begin();
frame = {INT_MAX, INT_MAX, 0, 0}; frame = {INT_MAX, INT_MAX, 0, 0};
while(iter != choices.end()){ while(iter != choices.end()){
rectangle otherFrame = iter->second->getBounds(); rectangle otherFrame = iter->second->getBounds();
@@ -47,14 +47,17 @@ void cLedGroup::recalcRect(){
} }
void cLedGroup::addChoice(cLed* ctrl, std::string key) { void cLedGroup::addChoice(cLed* ctrl, std::string key) {
choices[key] = ctrl; // normal ledgroups add their children through parseChildControl, but mapgroups still
// need to do it this way
if(!hasChild(key))
choices[key] = ctrl;
if(ctrl->getState() != led_off) if(ctrl->getState() != led_off)
setSelected(key); setSelected(key);
} }
bool cLedGroup::handleClick(location where, cFramerateLimiter& fps_limiter) { bool cLedGroup::handleClick(location where, cFramerateLimiter& fps_limiter) {
std::string which_clicked; std::string which_clicked;
ledIter iter = choices.begin(); ctrlIter iter = choices.begin();
while(iter != choices.end()){ while(iter != choices.end()){
if(iter->second->isVisible() && where.in(iter->second->getBounds())){ if(iter->second->isVisible() && where.in(iter->second->getBounds())){
if(iter->second->handleClick(where, fps_limiter)) { if(iter->second->handleClick(where, fps_limiter)) {
@@ -84,17 +87,19 @@ void cLedGroup::callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std
if(choices[which_clicked]->triggerClickHandler(me,which_clicked,mods)){ if(choices[which_clicked]->triggerClickHandler(me,which_clicked,mods)){
if(onClick) onClick(me,id,mods); if(onClick) onClick(me,id,mods);
if(!curSelect.empty()) { if(!curSelect.empty()) {
choices[curSelect]->setState(led_off); cLed& sel = getChild(curSelect);
if(!choices[curSelect]->triggerFocusHandler(me,curSelect,true)){ sel.setState(led_off);
choices[curSelect]->setState(led_red); if(!sel.triggerFocusHandler(me,curSelect,true)){
sel.setState(led_red);
return; return;
} }
} }
choices[which_clicked]->setState(led_red); cLed& led = getChild(which_clicked);
if(!choices[which_clicked]->triggerFocusHandler(me,which_clicked,false)){ led.setState(led_red);
if(!led.triggerFocusHandler(me,which_clicked,false)){
if(!curSelect.empty()) if(!curSelect.empty())
choices[curSelect]->setState(led_red); getChild(curSelect).setState(led_red);
choices[which_clicked]->setState(led_off); led.setState(led_off);
return; return;
} }
}else return; }else return;
@@ -104,8 +109,8 @@ void cLedGroup::callHandler(event_fcn<EVT_CLICK>::type onClick, cDialog& me, std
curSelect = which_clicked; curSelect = which_clicked;
if(!triggerFocusHandler(me,id,false)) { if(!triggerFocusHandler(me,id,false)) {
if(!curSelect.empty()) if(!curSelect.empty())
choices[curSelect]->setState(led_red); getChild(curSelect).setState(led_red);
choices[which_clicked]->setState(led_off); getChild(which_clicked).setState(led_off);
curSelect = prevSelect; curSelect = prevSelect;
prevSelect = savePrevSelect; prevSelect = savePrevSelect;
return; return;
@@ -157,48 +162,51 @@ bool cLedGroup::hasChild(std::string id) const {
} }
cLed& cLedGroup::getChild(std::string id){ cLed& cLedGroup::getChild(std::string id){
ledIter iter = choices.find(id); ctrlIter iter = choices.find(id);
if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup."); if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup.");
return *(iter->second); return dynamic_cast<cLed&>(*(iter->second));
} }
void cLedGroup::setSelected(std::string id){ void cLedGroup::setSelected(std::string id){
if(id == "") { // deselect all if(id == "") { // deselect all
if(curSelect == "") return; if(curSelect == "") return;
eLedState was = choices[curSelect]->getState(); cLed& sel = getChild(curSelect);
choices[curSelect]->setState(led_off); eLedState was = sel.getState();
if(choices[curSelect]->triggerFocusHandler(*getDialog(),curSelect,true)) sel.setState(led_off);
if(sel.triggerFocusHandler(*getDialog(),curSelect,true))
curSelect = ""; curSelect = "";
else else
choices[curSelect]->setState(was); sel.setState(was);
return; return;
} }
ledIter iter = choices.find(id); ctrlIter iter = choices.find(id);
if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup."); if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup.");
cLed& led = getChild(id);
if(curSelect == ""){ if(curSelect == ""){
if(iter->second->triggerFocusHandler(*getDialog(),curSelect,false)){ if(led.triggerFocusHandler(*getDialog(),curSelect,false)){
iter->second->setState(led_red); led.setState(led_red);
curSelect = iter->first; curSelect = id;
} }
}else{ }else{
cLed& sel = getChild(curSelect);
eLedState a, b; eLedState a, b;
a = choices[curSelect]->getState(); a = sel.getState();
b = iter->second->getState(); b = led.getState();
choices[curSelect]->setState(led_off); sel.setState(led_off);
iter->second->setState(led_red); led.setState(led_red);
if(!choices[curSelect]->triggerFocusHandler(*getDialog(),curSelect,true)){ if(!sel.triggerFocusHandler(*getDialog(),curSelect,true)){
choices[curSelect]->setState(a); sel.setState(a);
iter->second->setState(b); led.setState(b);
return; return;
} }
if(!iter->second->triggerFocusHandler(*getDialog(),curSelect,false)){ if(!led.triggerFocusHandler(*getDialog(),curSelect,false)){
choices[curSelect]->setState(a); sel.setState(a);
iter->second->setState(b); led.setState(b);
return; return;
} }
curSelect = iter->first; curSelect = id;
} }
} }
@@ -212,7 +220,7 @@ std::string cLedGroup::getPrevSelection() const {
void cLedGroup::draw(){ void cLedGroup::draw(){
if(!visible) return; if(!visible) return;
ledIter iter = choices.begin(); ctrlIter iter = choices.begin();
while(iter != choices.end()){ while(iter != choices.end()){
iter->second->draw(); iter->second->draw();
iter++; iter++;
@@ -242,8 +250,11 @@ bool cLedGroup::parseContent(ticpp::Node& content, int n, std::string tagName, s
std::string val = content.Value(); std::string val = content.Value();
int type = content.Type(); int type = content.Type();
if(type == TiXmlNode::ELEMENT && val == "led"){ if(type == TiXmlNode::ELEMENT && val == "led"){
auto led = getDialog()->parse<cLed>(dynamic_cast<ticpp::Element&>(content), *this); std::string id;
addChoice(led.second, led.first); if(!parseChildControl(dynamic_cast<ticpp::Element&>(content), choices, id, fname))
return false;
cLed* led = dynamic_cast<cLed*>(choices[id]);
addChoice(led, id);
return true; return true;
} else if(type == TiXmlNode::TEXT) { } else if(type == TiXmlNode::TEXT) {
return false; return false;

View File

@@ -34,7 +34,7 @@
/// so getSelected() will return the new selection. (This is the reason for the getPreviousSelection() method.) /// so getSelected() will return the new selection. (This is the reason for the getPreviousSelection() method.)
class cLedGroup : public cContainer { class cLedGroup : public cContainer {
friend class cTilemap; // So it can call parseAttribute friend class cTilemap; // So it can call parseAttribute
std::map<std::string,cLed*> choices; std::map<std::string,cControl*> choices;
std::string fromList; std::string fromList;
std::string curSelect, prevSelect; std::string curSelect, prevSelect;
std::string clicking; std::string clicking;
@@ -110,8 +110,6 @@ public:
/// If a choice is not within the bounding rect, it will not respond to clicks. /// If a choice is not within the bounding rect, it will not respond to clicks.
void recalcRect() override; void recalcRect() override;
void forEach(std::function<void(std::string,cControl&)> callback) 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; void draw() override;
}; };
#endif #endif