SlideBar.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. /******************************************************************************
  2. Don't try to disable _pixel_align for buttons,
  3. because the middle button would flicker when moved.
  4. /******************************************************************************/
  5. #include "stdafx.h"
  6. namespace EE{
  7. static GuiSkin GuiSkinTemp;
  8. #define CLIP_UNDER 1 // if adjust clipping so we don't draw underneath the SlideBar (looks better for semi-transparent SlideBars)
  9. /******************************************************************************/
  10. void SlideBar::zero()
  11. {
  12. sbc=SBC_STEP;
  13. _scroll_immediate=false;
  14. _scroll=false;
  15. _vertical=false;
  16. _usable=false; // keep it always as false when deleted
  17. _focusable=true;
  18. _scroll_to=0;
  19. _offset=0;
  20. _length=_length_total=0;
  21. _scroll_mul=0.5f;
  22. _scroll_add=0;
  23. _scroll_button=1.5f;
  24. _button_size=0;
  25. _func_immediate=false;
  26. _func_user=null;
  27. _func=null;
  28. }
  29. SlideBar::SlideBar() {zero();}
  30. SlideBar& SlideBar::del()
  31. {
  32. _skin.clear();
  33. REPA(button)button[i].del();
  34. super::del(); zero(); return T;
  35. }
  36. /******************************************************************************/
  37. void SlideBar::setButtonSubType()
  38. {
  39. button[0]._sub_type=BUTTON_TYPE_SLIDEBAR_CENTER;
  40. button[1]._sub_type=(_vertical ? BUTTON_TYPE_SLIDEBAR_RIGHT : BUTTON_TYPE_SLIDEBAR_LEFT ); // this is the "min" button (left /up ), because of how this button is positioned in the slidebar and how 'drawVertical' is performed, in vertical mode this actually needs to be drawn from the right skin
  41. button[2]._sub_type=(_vertical ? BUTTON_TYPE_SLIDEBAR_LEFT : BUTTON_TYPE_SLIDEBAR_RIGHT); // this is the "max" button (right/down), because of how this button is positioned in the slidebar and how 'drawVertical' is performed, in vertical mode this actually needs to be drawn from the left skin
  42. }
  43. void SlideBar::setParams()
  44. {
  45. _type=GO_SLIDEBAR;
  46. REPA(button)
  47. {
  48. Button &b=button[i];
  49. b._parent =this;
  50. b._vertical=_vertical;
  51. }
  52. setButtonSubType();
  53. }
  54. SlideBar& SlideBar::create()
  55. {
  56. del();
  57. _visible=true;
  58. _usable =true;
  59. _length =1;
  60. _length_total=11;
  61. REPA(button)
  62. {
  63. Button &b=button[i];
  64. b. create();
  65. b. mode =BUTTON_CONTINUOUS;
  66. b._focusable=false;
  67. }
  68. setParams();
  69. return T;
  70. }
  71. SlideBar& SlideBar::create(C SlideBar &src)
  72. {
  73. if(this!=&src)
  74. {
  75. if(!src.is())del();else
  76. {
  77. create().copyParams(src);
  78. _type =GO_SLIDEBAR;
  79. sbc =src. sbc;
  80. _scroll_immediate=src._scroll_immediate;
  81. _scroll =src._scroll;
  82. _vertical =src._vertical;
  83. _usable =src._usable;
  84. _focusable =src._focusable;
  85. _scroll_to =src._scroll_to;
  86. _offset =src._offset;
  87. _length =src._length;
  88. _length_total =src._length_total;
  89. _scroll_mul =src._scroll_mul;
  90. _scroll_add =src._scroll_add;
  91. _scroll_button =src._scroll_button;
  92. _button_size =src._button_size;
  93. _func_immediate =src._func_immediate;
  94. _func_user =src._func_user;
  95. _func =src._func;
  96. _skin =src._skin;
  97. REPAO(button).create(src.button[i])._parent=this;
  98. }
  99. }
  100. return T;
  101. }
  102. /******************************************************************************/
  103. void SlideBar::setButtonRect()
  104. {
  105. if(!App.closed()) // this may be called after app has closed, in which case the Gui Skin pointers are invalid which may cause crash
  106. {
  107. Rect r;
  108. Flt button_w=_button_size,
  109. button_h=_button_size;
  110. GuiSkin *skin1=button[1].getSkin(); GuiSkin::ButtonImage *image1=(skin1 ? _vertical ? &skin1->slidebar.right : &skin1->slidebar.left : null); // vertical mode has images swapped
  111. GuiSkin *skin2=button[2].getSkin(); GuiSkin::ButtonImage *image2=(skin2 ? _vertical ? &skin2->slidebar.left : &skin2->slidebar.right : null); // vertical mode has images swapped
  112. button[1].visible(image1 && (image1->normal || image1->image));
  113. button[2].visible(image2 && (image2->normal || image2->image));
  114. Int buttons=(button[1].visible()+button[2].visible());
  115. if(_vertical)
  116. {
  117. if(buttons)MIN(button_h, rect().h()/buttons);else button_h=0; // if buttons don't fit in space
  118. Flt space=rect().h()-buttons*button_h, size=(lengthTotal() ? space*Sat(length()/lengthTotal()) : 0), clamped_size=Max(size, Min(_button_size*0.9f, space));
  119. r.min.x=rect().min.x; r.max.y=rect().max.y-(space-clamped_size)*T(); if(button[1].visible())r.max.y-=button_h;
  120. r.max.x=rect().max.x; r.min.y= r.max.y- clamped_size;
  121. }else
  122. {
  123. if(buttons)MIN(button_w, rect().w()/buttons);else button_w=0; // if buttons don't fit in space
  124. Flt space=rect().w()-buttons*button_w, size=(lengthTotal() ? space*Sat(length()/lengthTotal()) : 0), clamped_size=Max(size, Min(_button_size*0.9f, space));
  125. r.min.y=rect().min.y; r.min.x=rect().min.x+(space-clamped_size)*T(); if(button[1].visible())r.min.x+=button_w;
  126. r.max.y=rect().max.y; r.max.x= r.min.x+ clamped_size;
  127. }
  128. button[0].rect( r); button[0]._vertical=_vertical;
  129. button[1].rect(Rect(rect().min.x , rect().max.y-button_h*button[1].visible(), rect().min.x+button_w*button[1].visible(), rect().max.y )); button[1]._vertical=_vertical;
  130. button[2].rect(Rect(rect().max.x-button_w*button[2].visible(), rect().min.y , rect().max.x , rect().min.y+button_h*button[2].visible())); button[2]._vertical=_vertical;
  131. }
  132. }
  133. /******************************************************************************/
  134. SlideBar& SlideBar::setLengths(Flt length, Flt length_total)
  135. {
  136. if(is()) // don't enable '_usable' when deleted
  137. {
  138. MAX(length , 0);
  139. MAX(length_total, 0);
  140. T._length =length;
  141. T._length_total=length_total;
  142. T._usable =(length+EPS<length_total);
  143. return setOffset(_offset, false);
  144. }
  145. return T;
  146. }
  147. SlideBar& SlideBar::set(Flt frac, SET_MODE mode)
  148. {
  149. return setOffset(Sat(frac)*(lengthTotal()-length()), true, mode);
  150. }
  151. SlideBar& SlideBar::offset(Flt offset, SET_MODE mode)
  152. {
  153. return setOffset(offset, true, mode);
  154. }
  155. Flt SlideBar::operator() ()C {Flt d=lengthTotal()-length(); return d ? _offset/d : 0;}
  156. Flt SlideBar::wantedOffset()C {return _scroll ? _scroll_to : _offset;}
  157. /******************************************************************************/
  158. SlideBar& SlideBar::func(void (*func)(Ptr), Ptr user, Bool immediate)
  159. {
  160. T._func =func;
  161. T._func_user =user;
  162. T._func_immediate=immediate;
  163. return T;
  164. }
  165. void SlideBar::call()
  166. {
  167. if(_func)if(_func_immediate)_func(_func_user);else Gui.addFuncCall(_func, _func_user);
  168. }
  169. /******************************************************************************/
  170. SlideBar& SlideBar::focusable(Bool on) {if(_focusable!=on){_focusable=on; if(!on)kbClear();} return T;}
  171. /******************************************************************************/
  172. SlideBar& SlideBar::desc(C Str &desc)
  173. {
  174. super ::desc(desc);
  175. button[0].desc(desc);
  176. button[1].desc(desc);
  177. button[2].desc(desc);
  178. return T;
  179. }
  180. SlideBar& SlideBar::rect(C Rect &rect)
  181. {
  182. if(T.rect()!=rect)
  183. {
  184. super::rect(rect);
  185. if(_vertical!=T.rect().vertical())
  186. {
  187. _vertical^=1;
  188. setButtonSubType();
  189. }
  190. _button_size=(_vertical ? T.rect().w() : T.rect().h());
  191. setButtonRect();
  192. }
  193. return T;
  194. }
  195. SlideBar& SlideBar::move(C Vec2 &delta)
  196. {
  197. if(delta.any())
  198. {
  199. super::move(delta);
  200. button[0].move(delta);
  201. button[1].move(delta);
  202. button[2].move(delta);
  203. }
  204. return T;
  205. }
  206. /******************************************************************************/
  207. SlideBar& SlideBar::setOffset(Flt offset, Bool stop, SET_MODE mode)
  208. {
  209. if(stop)_scroll=false;
  210. offset=Max(0, Min(offset, lengthTotal()-length()));
  211. if(T._offset!=offset)
  212. {
  213. T._offset=offset;
  214. if(mode!=QUIET)call();
  215. }
  216. setButtonRect();
  217. return T;
  218. }
  219. SlideBar& SlideBar::scroll(Flt delta, Bool immediate)
  220. {
  221. if(immediate)
  222. {
  223. if(_scroll)_scroll_to=Max(0, Min(_scroll_to+delta, lengthTotal()-length())); // adjust current scrolling if any
  224. setOffset(_offset+delta, false); // adjust current offset but without stopping
  225. }else
  226. {
  227. if(_scroll && Sign(_scroll_to-_offset)==Sign(delta))_scroll_to+=delta ; // if currently scrolling and in the same direction
  228. else _scroll_to =delta+_offset;
  229. _scroll_to=Max(0, Min(_scroll_to, lengthTotal()-length()));
  230. _scroll =true;
  231. }
  232. return T;
  233. }
  234. SlideBar& SlideBar::scrollTo(Flt pos, Bool immediate)
  235. {
  236. Flt min=Max(0, Min(pos, lengthTotal()-length())),
  237. max=Max(0, Min(pos, lengthTotal() ));
  238. if(min<_offset ){_scroll=true ; _scroll_to=min ;}else
  239. if(max>_offset+length()){_scroll=true ; _scroll_to=max-length();}else
  240. {_scroll=false; _scroll_to=_offset ;}
  241. return immediate ? setOffset(_scroll_to) : T;
  242. }
  243. SlideBar& SlideBar::scrollFit(Flt min, Flt max, Bool immediate)
  244. {
  245. min=Max(0, Min(min, lengthTotal()-length()));
  246. max=Max(0, Min(max, lengthTotal() ));
  247. if(min<_offset ){_scroll=true ; _scroll_to=min ;}else
  248. if(max>_offset+length()){_scroll=true ; _scroll_to=max-length();}else
  249. {_scroll=false; _scroll_to= _offset ;}
  250. return immediate ? setOffset(_scroll_to) : T;
  251. }
  252. SlideBar& SlideBar::scrollEnd(Bool immediate) {return scrollTo(lengthTotal(), immediate);}
  253. SlideBar& SlideBar::scrollOptions(Flt relative, Flt base, Bool immediate, Flt button_speed)
  254. {
  255. T._scroll_mul =Max(0, relative);
  256. T._scroll_add =Max(0, base );
  257. T._scroll_immediate=immediate;
  258. T._scroll_button =Max(0, button_speed);
  259. return T;
  260. }
  261. SlideBar& SlideBar::removeSideButtons()
  262. {
  263. button[1].del();
  264. button[2].del();
  265. setButtonRect();
  266. return T;
  267. }
  268. SlideBar& SlideBar::skin(C GuiSkinPtr &skin)
  269. {
  270. if(_skin!=skin)
  271. {
  272. _skin=skin;
  273. REPAO(button).skin=skin;
  274. setButtonRect();
  275. }
  276. return T;
  277. }
  278. /******************************************************************************/
  279. GuiObj* SlideBar::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel)
  280. {
  281. if(GuiObj *go=super::test(gpc, pos, mouse_wheel))
  282. {
  283. if(_usable)mouse_wheel=this;
  284. if(GuiObj *go=button[2].test(gpc, pos, mouse_wheel))return go;
  285. if(GuiObj *go=button[1].test(gpc, pos, mouse_wheel))return go;
  286. if(GuiObj *go=button[0].test(gpc, pos, mouse_wheel))return go;
  287. return go;
  288. }
  289. return null;
  290. }
  291. /******************************************************************************/
  292. void SlideBar::update(C GuiPC &gpc)
  293. {
  294. GuiPC gpc2(gpc, visible(), enabled());
  295. if( gpc2.enabled)
  296. {
  297. Int scroll_discrete=0;
  298. Flt scroll_smooth =0;
  299. // check for click on the back
  300. switch(sbc)
  301. {
  302. case SBC_STEP:
  303. case SBC_SMOOTH:
  304. {
  305. REPA(MT)if(MT.guiObj(i)==this && MT.bp(i))
  306. {
  307. if(sbc==SBC_STEP)
  308. {
  309. if(_vertical)scroll_discrete-=Sign(MT.pos(i).y-(button[0].rect().centerY()+gpc.offset.y));
  310. else scroll_discrete+=Sign(MT.pos(i).x-(button[0].rect().centerX()+gpc.offset.x));
  311. }else // change focus to buttons
  312. {
  313. if(_vertical)MT.guiObj(i, &button[(MT.pos(i).y>button[0].rect().centerY()+gpc.offset.y) ? 1 : 2]);
  314. else MT.guiObj(i, &button[(MT.pos(i).x<button[0].rect().centerX()+gpc.offset.x) ? 1 : 2]);
  315. }
  316. }
  317. }break;
  318. case SBC_SET_POS:
  319. {
  320. REPA(MT)if(MT.guiObj(i)==this && (MT.state(i)&(BS_ON|BS_PUSHED))) // check for 'bp' as well because single touchpad taps are not registered as 'b'
  321. {
  322. if(_vertical){Flt h_2=button[0].rect().h()*0.5f; set(LerpR(button[1].rect().min.y-h_2, button[2].rect().max.y+h_2, MT.pos(i).y-gpc.offset.y));}
  323. else {Flt w_2=button[0].rect().w()*0.5f; set(LerpR(button[1].rect().max.x+w_2, button[2].rect().min.x-w_2, MT.pos(i).x-gpc.offset.x));}
  324. }
  325. }break;
  326. }
  327. if(Gui.wheel()==this)
  328. {
  329. scroll_smooth-=Ms.wheel();
  330. }
  331. if(Gui.kb()==this)
  332. {
  333. if(_vertical)
  334. {
  335. if(Kb.b(KB_UP ))button[1].push();
  336. if(Kb.b(KB_DOWN))button[2].push();
  337. }else
  338. {
  339. if(Kb.b(KB_LEFT ))button[1].push();
  340. if(Kb.b(KB_RIGHT))button[2].push();
  341. }
  342. scroll_discrete+=Kb.k(KB_PGDN);
  343. scroll_discrete-=Kb.k(KB_PGUP);
  344. if(Kb.k(KB_HOME)){scrollTo(0 ); scroll_discrete=0;}
  345. if(Kb.k(KB_END )){scrollTo(lengthTotal()); scroll_discrete=0;}
  346. }
  347. // buttons
  348. button[0].update(gpc2);
  349. button[1].update(gpc2);
  350. button[2].update(gpc2);
  351. if((button[0]() || button[1]() || button[2]()) && _usable)
  352. {
  353. Flt d=0;
  354. if(button[0]())REPA(MT)if(MT.guiObj(i)==&button[0] && MT.b(i))
  355. {
  356. if(_vertical)d-=MT.dc(i).y*lengthTotal()/(button[1].rect().min.y-button[2].rect().max.y);
  357. else d+=MT.dc(i).x*lengthTotal()/(button[2].rect().min.x-button[1].rect().max.x);
  358. }
  359. if(button[1]())d-=Time.ad()*_scroll_button;
  360. if(button[2]())d+=Time.ad()*_scroll_button;
  361. setOffset(_offset+d);
  362. }
  363. // scroll
  364. if( scroll_discrete || scroll_smooth)scroll((scroll_discrete+scroll_smooth)*(_scroll_mul*length()+_scroll_add), _scroll_immediate);
  365. if(_scroll )
  366. {
  367. if(_scroll_immediate || Equal(_scroll_to, _offset, 0.001f))setOffset(_scroll_to);else
  368. {
  369. Flt offset=T._offset; AdjustValTime(offset, _scroll_to, 0.0001f, Time.ad());
  370. setOffset(offset, false);
  371. }
  372. }
  373. }
  374. }
  375. /******************************************************************************/
  376. void SlideBar::draw(C GuiPC &gpc)
  377. {
  378. if(visible() && gpc.visible)
  379. if(GuiSkin *skin=getSkin())
  380. {
  381. Rect r=rect()+gpc.offset, ext_rect;
  382. if(skin->slidebar.background)skin->slidebar.background->extendedRect(r, ext_rect);else ext_rect=r;
  383. if(Cuts(ext_rect, gpc.clip))
  384. {
  385. D.clip(gpc.clip);
  386. // background
  387. Rect background_rect=r;
  388. if(_vertical)
  389. {
  390. background_rect.min.y=button[2].rect().max.y+gpc.offset.y;
  391. background_rect.max.y=button[1].rect().min.y+gpc.offset.y;
  392. }else
  393. {
  394. background_rect.min.x=button[1].rect().max.x+gpc.offset.x;
  395. background_rect.max.x=button[2].rect().min.x+gpc.offset.x;
  396. }
  397. if(skin->slidebar.background)
  398. {
  399. if(_vertical)skin->slidebar.background->drawVertical(skin->slidebar.background_color, TRANSPARENT, background_rect);
  400. else skin->slidebar.background->draw (skin->slidebar.background_color, TRANSPARENT, background_rect);
  401. }else
  402. if(skin->slidebar.background_color.a)background_rect.draw(skin->slidebar.background_color);
  403. // scroll target
  404. if(_scroll && _usable)
  405. if(GuiSkin *button_skin=button[0].getSkin())
  406. if(Flt d=lengthTotal()-length())
  407. {
  408. d=(_scroll_to-_offset)/d;
  409. Button button_temp; button_temp.create(button[0]);
  410. // !! do a fast copy that avoids expensive cache elm assignment, must be in sync with 'Zero' below !!
  411. CopyFast(GuiSkinTemp.slidebar.center, button_skin->slidebar.center);
  412. GuiSkinTemp.slidebar.center.normal_color.a=((GuiSkinTemp.slidebar.center.normal_color.a*96)>>8);
  413. GuiSkinTemp.slidebar.center.pushed_color.a=((GuiSkinTemp.slidebar.center.pushed_color.a*96)>>8);
  414. button_temp.skin=&GuiSkinTemp;
  415. #if CLIP_UNDER
  416. GuiPC temp=gpc;
  417. #endif
  418. if(_vertical)
  419. {
  420. d*=button[1].rect().min.y-button[2].rect().max.y-button[0].rect().h();
  421. button_temp._rect.min.y-=d;
  422. button_temp._rect.max.y-=d;
  423. #if CLIP_UNDER
  424. if(d>0)MIN(temp.clip.max.y, button[0].rect().min.y+gpc.offset.y); // sliding down
  425. else MAX(temp.clip.min.y, button[0].rect().max.y+gpc.offset.y); // sliding up
  426. #endif
  427. }else
  428. {
  429. d*=button[2].rect().min.x-button[1].rect().max.x-button[0].rect().w();
  430. button_temp._rect.min.x+=d;
  431. button_temp._rect.max.x+=d;
  432. #if CLIP_UNDER
  433. if(d<0)MIN(temp.clip.max.x, button[0].rect().min.x+gpc.offset.x); // sliding left
  434. else MAX(temp.clip.min.x, button[0].rect().max.x+gpc.offset.x); // sliding right
  435. #endif
  436. }
  437. #if CLIP_UNDER
  438. button_temp.draw(temp);
  439. #else
  440. button_temp.draw(gpc);
  441. #endif
  442. // !! do a fast clear that avoids expensive cache elm release, must be in sync with 'Copy' above !!
  443. Zero(GuiSkinTemp.slidebar.center);
  444. }
  445. button[0].draw(gpc);
  446. if(button[1].is())button[1].draw(gpc);
  447. if(button[2].is())button[2].draw(gpc);
  448. if(Gui.kb()==this)Gui.kbLit(this, r, skin);
  449. }
  450. }
  451. }
  452. /******************************************************************************/
  453. Bool SlideBar::save(File &f, CChar *path)C
  454. {
  455. if(super::save(f, path))
  456. {
  457. f.putMulti(Byte(6), sbc, _scroll_immediate, _vertical, _usable, _focusable, _offset, _length, _length_total); // version
  458. f.putMulti(_scroll_mul, _scroll_add, _scroll_button, _button_size);
  459. f.putAsset(_skin.id());
  460. if(button[0].save(f, path))
  461. if(button[1].save(f, path))
  462. if(button[2].save(f, path))
  463. return f.ok();
  464. }
  465. return false;
  466. }
  467. Bool SlideBar::load(File &f, CChar *path)
  468. {
  469. del(); if(super::load(f, path))switch(f.decUIntV()) // version
  470. {
  471. case 6:
  472. {
  473. f.getMulti(sbc, _scroll_immediate, _vertical, _usable, _focusable, _offset, _length, _length_total);
  474. f.getMulti(_scroll_mul, _scroll_add, _scroll_button, _button_size);
  475. _skin.require(f.getAssetID(), path);
  476. if(button[0].load(f, path))
  477. if(button[1].load(f, path))
  478. if(button[2].load(f, path))
  479. if(f.ok()){setParams(); setButtonRect(); return true;} // call 'setButtonRect' because it may be dependent on current 'Gui.skin'
  480. }break;
  481. case 5:
  482. {
  483. f>>sbc>>_scroll_immediate>>_vertical>>_usable>>_focusable>>_offset>>_length>>_length_total>>_scroll_mul>>_scroll_add>>_scroll_button>>_button_size;
  484. _skin.require(f._getAsset(), path);
  485. if(button[0].load(f, path))
  486. if(button[1].load(f, path))
  487. if(button[2].load(f, path))
  488. if(f.ok()){setParams(); setButtonRect(); return true;} // call 'setButtonRect' because it may be dependent on current 'Gui.skin'
  489. }break;
  490. case 4:
  491. {
  492. f>>_focusable; f.skip(4); f>>_scroll_immediate>>_vertical>>_usable>>_offset>>_length>>_length_total>>_scroll_mul>>_scroll_add>>_scroll_button>>_button_size>>sbc;
  493. f._getStr();
  494. if(button[0].load(f, path))
  495. if(button[1].load(f, path))
  496. if(button[2].load(f, path))
  497. if(f.ok()){setParams(); setButtonRect(); return true;} // call 'setButtonRect' because it may be dependent on current 'Gui.skin'
  498. }break;
  499. case 3:
  500. {
  501. f>>_focusable; f.skip(4); f>>_scroll_immediate>>_vertical>>_usable>>_offset>>_length>>_length_total>>_scroll_mul>>_scroll_add>>_scroll_button>>_button_size; sbc=SBC_STEP;
  502. f._getStr();
  503. if(button[0].load(f, path))
  504. if(button[1].load(f, path))
  505. if(button[2].load(f, path))
  506. if(f.ok()){setParams(); setButtonRect(); return true;} // call 'setButtonRect' because it may be dependent on current 'Gui.skin'
  507. }break;
  508. case 2:
  509. {
  510. f>>_focusable; f.skip(4); f>>_scroll_immediate>>_vertical>>_usable>>_offset>>_length>>_length_total>>_scroll_mul>>_scroll_add>>_button_size; sbc=SBC_STEP;
  511. f._getStr();
  512. if(button[0].load(f, path))
  513. if(button[1].load(f, path))
  514. if(button[2].load(f, path))
  515. if(f.ok()){setParams(); setButtonRect(); return true;} // call 'setButtonRect' because it may be dependent on current 'Gui.skin'
  516. }break;
  517. case 1:
  518. {
  519. f>>_focusable; f.skip(4); f>>_scroll_immediate>>_vertical>>_usable>>_offset>>_length>>_length_total>>_scroll_mul>>_scroll_add>>_button_size; sbc=SBC_STEP;
  520. f._getStr();
  521. if(button[0].load(f, path))
  522. if(button[1].load(f, path))
  523. if(button[2].load(f, path))
  524. if(f.ok()){setParams(); setButtonRect(); return true;} // call 'setButtonRect' because it may be dependent on current 'Gui.skin'
  525. }break;
  526. case 0:
  527. {
  528. f>>_focusable; f.skip(4); f>>_scroll_immediate>>_vertical>>_usable>>_offset>>_length>>_length_total>>_scroll_mul>>_scroll_add>>_button_size; sbc=SBC_STEP;
  529. if(button[0].load(f, path))
  530. if(button[1].load(f, path))
  531. if(button[2].load(f, path))
  532. if(f.ok()){setParams(); setButtonRect(); return true;} // call 'setButtonRect' because it may be dependent on current 'Gui.skin'
  533. }break;
  534. }
  535. del(); return false;
  536. }
  537. /******************************************************************************/
  538. }
  539. /******************************************************************************/