#include "../include/xcv_license.h" //PCH namespace Widgets95 {//-. //<-' /**************************** WIDGETS_95_Rollout::mouse_down_handler() **********/ bool ui::rollout::_mouse_down_handler(int local_x, int local_y) { //EXPERIMENTAL //spacebar_mouse_click? if(local_x==-1&&e.curr_modifiers) return true; if(local_y-_y_abs>ui_button_drop) { e.init_inside = e.prev_inside = false; return false; } redraw(); return false; } /**************************** WIDGETS_95_Rollout::mouse_held_down_handler() ****/ bool ui::rollout::_mouse_held_down_handler(int local_x, int local_y, bool inside) { if(local_y-_y_abs>ui_button_drop) { e.curr_inside = false; } if(e.init_inside) { if(inside!=e.prev_inside) redraw(); } return false; } /**************************** WIDGETS_95_Rollout::mouse_down_handler() **********/ bool ui::rollout::_mouse_up_handler(int local_x, int local_y, bool inside) { if(e.init_inside&&inside) { set_int_val(!_int_val); execute_callback(); } else redraw(); return false; } /********************************* WIDGETS_95_Rollout::draw() ***********/ static void xcv_rollout_draw(ui::control &c, ui::control &name, bool shut, int press, int active) { const int w = c._w, h = c._h; int x1 = 1, x2 = w-1; int y1 = 1, y2 = 1+ui_button_drop; //Eliminating SW white pixel sticking out of bottom. //window::draw_etched_rect(-1,-1,w+1,shut?ui_button_drop+1:h+3); if(shut) { window::draw_color(128); window::draw_border_rect(x1-1,y1-1,x2+1,y2+1,2|1); if(!press) //Shadow? { window::draw_color(255); window::draw_border_rect(x1-1,y1-1,x2+1,y2+1,4|8); window::draw_color(233); } else window::draw_color(255); window::draw_border_rect(x1-!press,y1-1,x2+1,y2+1,press?1|4|8:4|8); } else { int bot = h; //if(next()) //tab? { if(ui::control*n=c.next()) if(c.ROLLOUT&n->_box_behavior) bot+=2+ui_itemspacing; } window::draw_etched_rect(x1-1,y1-1,x2+1,bot); if(!press) //Shadow? { window::draw_color(175); window::draw_border_rect(x1,y1+1,x2-1,y2+1,8); window::draw_color(233); window::draw_border_rect(x1,y1-1,x2+1,y2+2,4); } } //The following should match button's appearance. //int save = h; //h = ui_button_drop; ((button*)this)->_draw(); //h = save; if(press) { //OVERKILL //window::draw_filled_rect(x1+1,y1,x2,y2,c.BOX_CLEAR); window::draw_color(); window::draw_border_rect(x1+1,y1,x2,y2,0xf<<4); window::draw_color(128); window::draw_border_rect(x1+1,y1,x2,y2); } else window::draw_raised_rect(x1,y1,x2,y2,0); window::draw_color(0); //I have no clue how to calculate this. int y = y1+(ui_button_drop-name._font.height)/2+2; int x = x1+std::max(w-name.name_span(),0)/2; name.draw_active_name(x,y+press,name._name,active==-1?-1:0); if(active==1) { //REMINDER: This tweak is concerned with label spacing //and collision with the stippled border. if(!press) window::draw_active_rect(4,4,w-5,ui_button_drop-2,false); else window::draw_active_rect(4,3,w-3,ui_button_drop-1,true); } /** Draw '+' or '-' **/ int icon = (shut?1|2:2)*(active!=-1?1:-1); window::draw_etched_bars(w-21,8+press,w-12,17+press,icon); } void ui::rollout::_draw() { int press = this==e::get_pressed(); int active = this==e::get_active(); //EXPERIMENTAL if(press&&e.spacebar_is_down&&e.curr_modifiers) press = 0; if(!_enabled) active = -1; xcv_rollout_draw(*this,*this,_int_val==0,press,active); } void ui::tab::_draw() { bool shut = empty(); //Degenerate tab should appear identical to a rollout. control *ch = _row.first_child(); if(ch&&ch->_hidden) ch = ch->next(); //YUCK control *cmp = _row.last_child(); if(cmp&&cmp->_hidden) cmp = cmp->prev(); //YUCK if(!ch||ch==cmp) { //UNFINISHED //What about the input model? if(!ch) ch = this; int press = ch==e::get_pressed(); int active = ch==e::get_active(); if(!_enabled||!ch->_enabled) active = -1; xcv_rollout_draw(*this,*ch,shut,press,active); return; } int l = _row._y_off_top; //button_align? int x1 = 1, x2 = _w-1; int y1 = l, y2 = l+ui_button_drop; //1 //I have no clue how to calculate this. int name_y = y1+(ui_button_drop-_font.height)/2+2; int y = y1-1; int y0 = y; //2022 if(!shut) y+=ui_button_drop-1; int bot = _h; //if(next()) //tab? { if(control*n=next()) if(ROLLOUT&n->_box_behavior) bot+=2+ui_itemspacing; } draw_etched_rect(x1-1,y,x2+1,bot); int iv = _int_val; bool pressed = false; control *ac = e::get_active(); if(ac&&ac->_parent_node==&_row) { pressed = ac==e::get_pressed(); extern int xcv_multiple_old_val; if(pressed) iv = xcv_multiple_old_val; } else ac = nullptr; int xx,x = x1, shadow = 0; bool cur2,cur = ch->_id==iv&&!shut; //RUN GRAY UP TOP LEFT SIDE? if(!shut) window::draw_color(128); if(!shut) window::draw_border_rect(0,y0,0,y,1); for(control*cch=ch,*cn;ch;ch=cn,cur=cur2) { cn = ch->next(); cur2 = cn&&cn->_id==iv&&!shut; int w = ch->_w; xx = x; x+=w; int press = 0; if(ch==ac) //Draw button's focus-rect? { press = pressed; //window::draw_active_rect(3-press,3-press,w-3+press,_h-3+press); window::draw_active_rect(xx+3,y0+4-press,x-4+press*2,y0+ui_button_drop-2+press,press); } int name_x = xx+std::max(w-ch->name_span(),0)/2; window::draw_active_name(name_x,name_y+press,ch->_name,ch->_enabled?0:-1); if(ch==cmp) //Last? { //RUN WHITE UP TOP RIGHT SIDE //int end = !cur&&!press; int end = !cur&&!press?1:-1; //y2+1? window::draw_color(press?255:233); window::draw_border_rect(x,y0+(!cur||press),x+1,y2-end,4); } if(press) { window::draw_color(128); window::draw_border_rect(xx+1,y1,x,y2); //FOCUS-RECT BUSINESS window::draw_color(shadow?233:255); window::draw_border_rect(xx,y0,xx,y+2,1); //ERASE ETCHED BAR DAMAGE window::draw_color(); window::draw_border_rect(xx+2,y2-2,x,y2-2,2); shadow = 0; continue; } else window::draw_raised_rect(xx,y1,x,y2,cur?8:0); //HORIZONTAL/VERTICAL WHITE SHADOW window::draw_color(233); if(!cur) window::draw_border_rect(xx,y1,x+!cur2,y2,shadow|8); //RAISED TOP //Note: If stacking rollouts/tabs this will //probably be swallowed up into the previous //element. This way it further highlights the //displayed tab. if(cur) window::draw_color(128); if(cur) window::draw_border_rect(xx-1,y0,x+1,y2,2); shadow = 1; continue; } } /***************************** WIDGETS_95_Rollout::update_area() **********/ static void xcv_rollout_update_area(ui::control &c) { //May adjust or make room for a scrollbar. c._x_lr = c._x_rl = ui_edgespacing+2; //Note: Both rollout and tab pack tightly. ui::control *n = c.next(); bool btb = n&&n->_box_behavior&c.ROLLOUT; //Back-to-back? //Trying to move this logic out of _pack //subroutine by using y_off_bot. c._y_off_bot = ui_edgespacing-3; //I.e. _members_init. if(!btb) c._y_off_bot+=2+ui_itemspacing; //I.e. _pack. //REMOVE ME? //Cheating... should adjust y_off_top? if(c._shut()) c._h = ui_button_drop+(btb?-2:2); } void ui::rollout::_update_area() { //NOTE: SHUT is used to not do this in the constructor, //and since tab's case is more ambiguous than rollout's. if(_shut()!=!_int_val) set_int_val(!_int_val); _w = std::max(_w,name_span()+36); if(_w%2!=0) _w++; //Odds squares focus rect. xcv_rollout_update_area(*this); } void ui::tab::_update_area() { //Emptiness is represented by clearing multiple's text. bool shut = _shut(); if(shut!=empty()) if(shut) clear(); else set_int_val(_int_val); _row.pos("abs"); _row._x_abs = _x_abs; _row._y_abs = _y_abs; _w = std::max(_w,_row._w+2); xcv_rollout_update_area(*this); } void ui::rollout::_update_live() { if(_shut()!=!_int_val) { if(_shut()) { _box_behavior&=~PANELDRAW; } else _box_behavior|=PANELDRAW; repack(); } } void ui::tab::_update_live() { multiple::_update_live(&_row); //Emptiness is represented by clearing multiple's text. if(_shut()!=empty()) { if(_shut()) { _box_behavior&=~PANELDRAW; } else _box_behavior|=PANELDRAW; repack(); } } //---. }//<-'