#include "../include/xcv_license.h" //PCH namespace Widgets95 {//-. //<-' int xcv_multiple_old_val = 0; //extern static int xcv_multiple_old_val2 = 0; static ui::control *xcv_multiple_old_val3 = nullptr; /********************************* WIDGETS_95_RadioGroup::select_id() **********/ void ui::multiple::_update_live(control *c) { if(!c) c = this; //REFERENCE //While neat, this strategy is undesirable //because it requires a value to exist for //select_id to work. I think it's handy if //code can do that whichever order is best. //bool nonempty = false; int i = _int_val; control *ch = c->first_child(); for(;ch;ch=ch->next()) { if(ch->_box_behavior) { _update_live(ch); } else if(dynamic_cast(ch)) { if(this!=c) if(this!=((item*)ch)->find_multiple()) { return; //Entered nested multiple? } if(i==ch->_id&&!empty()) { //nonempty = true; //Reminder: style_fuzz accepts -1 or 1. if(!ch->_int_val) ch->set_int_val(1); } else if(ch->_int_val) ch->set_int_val(0); } } //This lets -1 be used to clear the items without //making it unrepresentable. //if(!nonempty) _text.clear(); } /**************************** multiple::special_handler() **********/ bool ui::multiple::_special_handler(int key, int modifiers) { //NOTE: This handler is for wheel only. int s; if(key==GLUT_KEY_UP||key==GLUT_KEY_LEFT) { s = -1; } else if(key==GLUT_KEY_DOWN||key==GLUT_KEY_RIGHT) { s = +1; } else return true; if(control*p=find(_int_val)) { //HACK: Multi-level wheel support. //while(p=s<0?p->prev():p->next()) while(p=s<0?_ui->_find_prev_control(p):_ui->_find_next_control(p)) { if(item*i=dynamic_cast(p)) { if(this==i->find_multiple()) { if(_int_val!=p->_id||_text.empty()) { set_int_val(p->_id); execute_callback(); } else assert(0); //Always? } break; } else //Still inside? { node *pp = p; for(pp=p;pp=pp->_parent_node;) if(this==pp) break; if(this==pp) continue; } break; } } return false; } /************************ WIDGETS_95_RadioButton::mouse_down_handler() **********/ bool ui::multiple::item::_mouse_down_handler(int local_x, int local_y) { if(multiple*m=find_multiple()) { //NOTE: This is very simple except for the introduction //of the "clear" concept and "fuzzy" (tri-state) values. int old = m->_int_val; xcv_multiple_old_val = old; if(xcv_multiple_old_val3=m->find([=](control *cmp) { return cmp->_id==old &&dynamic_cast(cmp) &&m==((item*)cmp)->find_multiple(); })) xcv_multiple_old_val2 = xcv_multiple_old_val3->_int_val; else xcv_multiple_old_val2 = 0; _fuzzy_set_int_val(); m->set_int_val(_id); return false; } else assert(m); return true; } /********************** WIDGETS_95_RadioButton::mouse_held_down_handler() ******/ bool ui::multiple::item::_mouse_held_down_handler(int local_x, int local_y, bool inside) { //REMINDER: _mouse_up_handler IS PIGGYBACKED ON THIS CODE. //MAKE THIS A SUBROUTINE BEFORE ADDING MORE FUNCTIONALITY. if(inside!=e.prev_inside) { _fuzzy_set_int_val(); if(multiple*m=find_multiple()) { //Gets more compilcated if there is a clear state. //m->set_int_val(inside?_id:xcv_multiple_old_val); m->stage_live(inside?&_id:&xcv_multiple_old_val); if(!xcv_multiple_old_val2&&!inside) m->_text.clear(); m->post_live(); if(-1==xcv_multiple_old_val2&&!inside) //YUCK xcv_multiple_old_val3->_int_val = -1; } else assert(m); } return false; } /*************************** WIDGETS_95_RadioButton::mouse_up_handler() **********/ bool ui::multiple::item::_mouse_up_handler(int local_x, int local_y, bool inside) { multiple *m = find_multiple(); assert(m); if(m) if(!inside) { //HACK: I THINK THIS CAN'T POSSIBLY OCCUR BY WAY OF //ACTUAL MOUSE-EVENTS, BUT HESITATE TO FULLY REMOVE //IT. IT NOW PIGGYBACKS ON _mouse_held_down_handler. //THE LOGIC IS TOO MUCH TO REPEAT HERE IN THIS CASE. if(e.prev_inside) { assert(!e.prev_inside); _mouse_held_down_handler(local_x,local_y,inside); } } else { /** Now we update the radio button group. We tell the group handler to set the currently-selected item to this button, which is reference by its user_id/ordinal number within group **/ m->set_int_val(_id); /*** Now update the linked variable, and call the callback, but ONLY if the value of the radio group actually changed ***/ if(m->_int_val!=xcv_multiple_old_val) { fuzzy: m->execute_callback(); } else if(style()&style_fuzz) { assert(xcv_multiple_old_val==_id); //NEW goto fuzzy; } else //listbar? { assert(xcv_multiple_old_val==_id|| m->_text.empty()&&m->_space_clicks); } } redraw(); return false; //tab seems to need redraw? } //---. }//<-'