Region.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. GuiPC::GuiPC(C GuiPC &old, Region &region)
  6. {
  7. T=old;
  8. visible &=region.visible();
  9. enabled &=region.enabled();
  10. client_rect=region.clientRect()+offset;
  11. offset =client_rect.lu();
  12. offset.x -=region.slidebar[0].offset();
  13. offset.y +=region.slidebar[1].offset();
  14. GuiSkin *skin=region.getSkin(); if(skin && skin->region.normal && skin->region.normal->pixelBorder())clip&=Rect(client_rect).extend(-D._pixel_size);else clip&=client_rect; // if the panel draws 1-pixel-border then leave it, this is so that Region children will not draw on top of it, because border should look like it's on top
  15. if(1)D.alignScreenToPixel(offset);
  16. }
  17. /******************************************************************************/
  18. void Region::zero()
  19. {
  20. kb_lit=true; _flag=0;
  21. _slidebar_size=0.05f;
  22. _crect.zero();
  23. }
  24. Region::Region() {zero();}
  25. Region& Region::del()
  26. {
  27. _children .del ();
  28. slidebar[0].del ();
  29. slidebar[1].del ();
  30. view .del ();
  31. _skin .clear();
  32. super::del(); zero(); return T;
  33. }
  34. void Region::setParent(Bool on)
  35. {
  36. slidebar[0]._parent=slidebar[1]._parent=view._parent=(on ? this : null);
  37. }
  38. void Region::setParams()
  39. {
  40. _type=GO_REGION;
  41. view._sub_type=BUTTON_TYPE_REGION_VIEW;
  42. setParent();
  43. }
  44. Region& Region::create()
  45. {
  46. del();
  47. _visible=true;
  48. view .create().mode=BUTTON_CONTINUOUS;
  49. slidebar[0].create().setLengths(0, 0).hide();
  50. slidebar[1].create().setLengths(0, 0).hide();
  51. view._focusable=slidebar[0]._focusable=slidebar[1]._focusable=false;
  52. setParams();
  53. return T;
  54. }
  55. Region& Region::create(C Region &src)
  56. {
  57. if(this!=&src)
  58. {
  59. if(!src.is())del();else
  60. {
  61. _children.del();
  62. copyParams(src);
  63. _type =GO_REGION;
  64. kb_lit =src. kb_lit;
  65. _slidebar_size=src._slidebar_size;
  66. _flag =src._flag;
  67. _skin =src._skin;
  68. _crect =src._crect;
  69. view .create(src.view );
  70. slidebar[0].create(src.slidebar[0]);
  71. slidebar[1].create(src.slidebar[1]);
  72. setParent();
  73. }
  74. }
  75. return T;
  76. }
  77. /******************************************************************************/
  78. void Region::childRectChanged(C Rect *old_rect, C Rect *new_rect, GuiObj &child)
  79. {
  80. // null rectangle means object is hidden
  81. if(old_rect || new_rect)
  82. {
  83. // decreasing size if old size was greater than virtual size and new size isn't
  84. Flt x=(new_rect ? GuiMaxX(*new_rect) : 0),
  85. y=(new_rect ? GuiMaxY(*new_rect) : 0),
  86. old_x=(old_rect ? GuiMaxX(*old_rect) : 0),
  87. old_y=(old_rect ? GuiMaxY(*old_rect) : 0);
  88. if((old_x>=virtualWidth ()-EPS && x<virtualWidth ()-EPS) // if decreasing in at least one dimension then we need to recalculate fully
  89. || (old_y>=virtualHeight()-EPS && y<virtualHeight()-EPS))virtualSize(null);else
  90. {
  91. // increasing size if new size is greater than virtual size
  92. Bool inc_w=(x>virtualWidth ()+EPS),
  93. inc_h=(y>virtualHeight()+EPS);
  94. if(inc_w || inc_h)
  95. {
  96. if(inc_w)slidebar[0]._length_total=x;
  97. if(inc_h)slidebar[1]._length_total=y;
  98. setButtons();
  99. }
  100. }
  101. }//else having null rectangles means object is hidden and we don't need to do anything
  102. }
  103. void Region::addChild(GuiObj &child)
  104. {
  105. if(_children.add(child, T))childRectChanged(null, child.visible() ? &child.rect() : null, child);
  106. }
  107. void Region::removeChild(GuiObj &child)
  108. {
  109. if(_children.remove(child))childRectChanged(child.visible() ? &child.rect() : null, null, child);
  110. }
  111. /******************************************************************************/
  112. Region& Region::removeSlideBars()
  113. {
  114. setParent(false); // detach before setting rectangle so virtual size won't be changed
  115. slidebar[0].del();
  116. slidebar[1].del();
  117. view .del();
  118. setButtons(); return T;
  119. }
  120. Bool Region::alwaysHideHorizontalSlideBar( )C {return FlagTest(_flag, ALWAYS_HIDE_HORIZONTAL_SLIDEBAR);}
  121. Region& Region::alwaysHideHorizontalSlideBar(Bool hide)
  122. {
  123. if(hide!=alwaysHideHorizontalSlideBar())
  124. {
  125. _flag^=ALWAYS_HIDE_HORIZONTAL_SLIDEBAR;
  126. setButtons();
  127. }
  128. return T;
  129. }
  130. void Region::setButtons()
  131. {
  132. Bool vertical, horizontal;
  133. Flt width =virtualWidth (),
  134. height=virtualHeight();
  135. Rect srect=_crect=rect();
  136. if( vertical =(slidebar[1].is() && height>clientHeight()+EPS)){srect.max.x-=slidebarSize(); _crect.max.x-=slidebarSize();}
  137. if( horizontal=(slidebar[0].is() && width >clientWidth ()+EPS)){srect.min.y+=slidebarSize(); if(!alwaysHideHorizontalSlideBar())_crect.min.y+=slidebarSize();
  138. if(!vertical && slidebar[1].is() && height>clientHeight()+EPS ){srect.max.x-=slidebarSize(); _crect.max.x-=slidebarSize(); vertical=true;}}
  139. setParent(false); // detach before setting rectangle so virtual size won't be changed
  140. slidebar[0].setLengths(clientWidth (), width ).rect(Rect(rect().min.x , rect().min.y, srect .max.x, rect().min.y+slidebarSize())); slidebar[0].visible(slidebar[0]._usable && !alwaysHideHorizontalSlideBar());
  141. slidebar[1].setLengths(clientHeight(), height).rect(Rect(rect().max.x-slidebarSize(), srect .min.y, rect().max.x, rect().max.y )); slidebar[1].visible(slidebar[1]._usable );
  142. view .rect(Rect(rect().max.x-slidebarSize(), rect().min.y, rect().max.x, rect().min.y+slidebarSize())).visible(slidebar[0]._usable && slidebar[1]._usable);
  143. setParent();
  144. }
  145. Vec2 Region::childrenSize()C
  146. {
  147. Vec2 size=0;
  148. REPA(_children)if(C GuiObj *c=_children[i])if(c->visible())
  149. {
  150. MAX(size.x, GuiMaxX(c->rect()));
  151. MAX(size.y, GuiMaxY(c->rect()));
  152. }
  153. return size;
  154. }
  155. Region& Region::slidebarSize(Flt size)
  156. {
  157. MAX(size, 0);
  158. if(_slidebar_size!=size)
  159. {
  160. _slidebar_size=size;
  161. setButtons();
  162. }
  163. return T;
  164. }
  165. Region& Region::virtualSize(C Vec2 *size)
  166. {
  167. Vec2 temp; if(!size)size=&(temp=childrenSize());
  168. slidebar[0]._length_total=size->x;
  169. slidebar[1]._length_total=size->y;
  170. setButtons(); return T;
  171. }
  172. Region& Region::rect(C Rect &rect)
  173. {
  174. if(T.rect()!=rect)
  175. {
  176. Rect old_client=localClientRect(), old_rect=T.rect(); T._rect=rect; setButtons(); // set manually instead of calling 'super::rect' because that will call 'notifyChildrenOfClientRectChange' before we finish setting client rectangle
  177. Rect new_client=localClientRect();
  178. notifyChildrenOfClientRectChange(&old_client, &new_client);
  179. notifyParentOfRectChange ( old_rect , visible() );
  180. }
  181. return T;
  182. }
  183. Region& Region::move(C Vec2 &delta)
  184. {
  185. if(delta.any())
  186. {
  187. super::move(delta);
  188. _crect += delta ;
  189. setParent(false); // detach before setting rectangle so virtual size won't be changed
  190. view .move(delta);
  191. slidebar[0].move(delta);
  192. slidebar[1].move(delta);
  193. setParent();
  194. }
  195. return T;
  196. }
  197. /******************************************************************************/
  198. Region& Region::skin(C GuiSkinPtr &skin, Bool sub_objects)
  199. {
  200. _skin=skin;
  201. if(sub_objects)
  202. {
  203. view .skin=skin ;
  204. REPAO(slidebar).skin(skin);
  205. }
  206. return T;
  207. }
  208. /******************************************************************************/
  209. GuiObj* Region::test(C GuiPC &gpc, C Vec2 &pos, GuiObj* &mouse_wheel)
  210. {
  211. if(GuiObj *go=super::test(gpc, pos, mouse_wheel))
  212. {
  213. if(!Kb.ctrlCmd()) // when Ctrl is hold then don't set mouse wheel focus to slidebars when we focus on Region, to allow child 'ComboBox' and 'Slider' to catch it, and if nothing is catched, then still leave empty so we don't accidentally scroll when using mouse wheel near ComboBox or Slider but accidentally not on it
  214. {
  215. Bool priority=!Kb.shift(); // when 'Kb.shift' disabled (default) then priority=1 (vertical), when enabled then priority=0 (horizontal)
  216. if(slidebar[ priority]._usable)mouse_wheel=&slidebar[ priority];else // check priority slidebar first
  217. if(slidebar[!priority]._usable)mouse_wheel=&slidebar[!priority]; // check !priority slidebar next
  218. }
  219. GuiPC gc (gpc, T ); if(GuiObj *go=_children.test(gc, pos, mouse_wheel))return go;
  220. GuiPC gpc2(gpc, visible(), enabled());
  221. if(GuiObj *go=slidebar[0].test(gpc2, pos, mouse_wheel))return go;
  222. if(GuiObj *go=slidebar[1].test(gpc2, pos, mouse_wheel))return go;
  223. if(GuiObj *go=view .test(gpc2, pos, mouse_wheel))return go;
  224. return go;
  225. }
  226. return null;
  227. }
  228. /******************************************************************************/
  229. void Region::update(C GuiPC &gpc)
  230. {
  231. GuiPC gpc2(gpc, visible(), enabled());
  232. if( gpc2.enabled)
  233. {
  234. view.update(gpc2);
  235. if(view())
  236. {
  237. if(Gui.ms()==&view)
  238. {
  239. Ms.freeze();
  240. slidebar[0].setOffset(slidebar[0]._offset + Ms.d().x*2);
  241. slidebar[1].setOffset(slidebar[1]._offset - Ms.d().y*2);
  242. }
  243. REPA(Touches)
  244. {
  245. Touch &t=Touches[i]; if(t.guiObj()==&view && t.on())
  246. {
  247. slidebar[0].setOffset(slidebar[0]._offset + t.d().x*2);
  248. slidebar[1].setOffset(slidebar[1]._offset - t.d().y*2);
  249. }
  250. }
  251. }
  252. // scroll horizontally
  253. if(Ms.wheelX()
  254. && (Gui.wheel()==&slidebar[0] || Gui.wheel()==&slidebar[1]) // if has focus on any of slidebars
  255. && slidebar[0]._usable) // we will scroll only horizontally, so check if that's possible
  256. slidebar[0].scroll(Ms.wheelX()*(slidebar[0]._scroll_mul*slidebar[0].length()+slidebar[0]._scroll_add), slidebar[0]._scroll_immediate);
  257. slidebar[0].update(gpc2);
  258. slidebar[1].update(gpc2);
  259. GuiPC gc(gpc, T); _children.update(gc);
  260. }
  261. }
  262. void Region::draw(C GuiPC &gpc)
  263. {
  264. if(visible() && gpc.visible)
  265. {
  266. GuiSkin *skin=getSkin();
  267. Rect rect=T.rect()+gpc.offset, ext_rect;
  268. if(skin && skin->region.normal)skin->region.normal->extendedRect(rect, ext_rect);else ext_rect=rect;
  269. if(Cuts(ext_rect, gpc.clip))
  270. {
  271. if(skin)
  272. {
  273. D.clip(gpc.clip);
  274. if(skin->region.normal )skin->region.normal->draw(skin->region.normal_color, rect);else
  275. if(skin->region.normal_color.a) rect.draw(skin->region.normal_color);
  276. }
  277. view .draw(gpc);
  278. slidebar[0].draw(gpc);
  279. slidebar[1].draw(gpc);
  280. GuiPC gc(gpc, T); _children.draw(gc);
  281. if(kb_lit && contains(Gui.kb())){D.clip(gpc.clip); Gui.kbLit(this, rect, skin);}
  282. }
  283. }
  284. }
  285. /******************************************************************************/
  286. Bool Region::save(File &f, CChar *path)C
  287. {
  288. if(super::save(f, path))
  289. {
  290. // !! in the future save '_flag' !!
  291. f.putMulti(Byte(3), kb_lit, _slidebar_size, _crect); // version
  292. f.putAsset(_skin.id());
  293. if(view .save(f, path))
  294. if(slidebar[0].save(f, path))
  295. if(slidebar[1].save(f, path))
  296. return f.ok();
  297. }
  298. return false;
  299. }
  300. Bool Region::load(File &f, CChar *path)
  301. {
  302. del(); if(super::load(f, path))switch(f.decUIntV()) // version
  303. {
  304. case 3:
  305. {
  306. f.getMulti(kb_lit, _slidebar_size, _crect);
  307. _skin.require(f.getAssetID(), path);
  308. if(view .load(f, path))
  309. if(slidebar[0].load(f, path))
  310. if(slidebar[1].load(f, path))
  311. if(f.ok()){setParams(); return true;}
  312. }break;
  313. case 2:
  314. {
  315. f>>kb_lit>>_slidebar_size>>_crect;
  316. _skin.require(f._getAsset(), path);
  317. if(view .load(f, path))
  318. if(slidebar[0].load(f, path))
  319. if(slidebar[1].load(f, path))
  320. if(f.ok()){setParams(); return true;}
  321. }break;
  322. case 1:
  323. {
  324. f>>kb_lit>>_slidebar_size>>_crect;
  325. if(view .load(f, path))
  326. if(slidebar[0].load(f, path))
  327. if(slidebar[1].load(f, path))
  328. if(f.ok()){f._getStr(); setParams(); return true;}
  329. }break;
  330. case 0:
  331. {
  332. f>>kb_lit>>_slidebar_size>>_crect;
  333. if(view .load(f, path))
  334. if(slidebar[0].load(f, path))
  335. if(slidebar[1].load(f, path))
  336. if(f.ok()){f._getStr8(); setParams(); return true;}
  337. }break;
  338. }
  339. del(); return false;
  340. }
  341. /******************************************************************************/
  342. }
  343. /******************************************************************************/