MenuBar.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. MenuBar::Elm::Elm()
  6. {
  7. hidden=0;
  8. x=0;
  9. w=0;
  10. }
  11. MenuBar::Elm& MenuBar::Elm::create(C Elm &src)
  12. {
  13. name=src. name;
  14. display_name=src.display_name;
  15. hidden=src. hidden;
  16. x=src. x;
  17. w=src. w;
  18. menu.create(src.menu);
  19. return T;
  20. }
  21. /******************************************************************************/
  22. void MenuBar::zero()
  23. {
  24. _alt=false;
  25. _lit=_push=_menu_prev=-1;
  26. }
  27. MenuBar::MenuBar() {zero();}
  28. MenuBar& MenuBar::del()
  29. {
  30. _elms.del ();
  31. _skin.clear();
  32. super::del(); zero(); return T;
  33. }
  34. MenuBar& MenuBar::create(C Node<MenuElm> &node)
  35. {
  36. del();
  37. _type =GO_MENU_BAR;
  38. _visible=true;
  39. _elms.setNum(node.children.elms());
  40. FREP(elms())
  41. {
  42. C Node<MenuElm> &src=node.children[i];
  43. Elm &elm=T.elm(i);
  44. elm.name =src.name;
  45. elm.display_name=src.display_name;
  46. elm.menu.create(src)._owner=this;
  47. Gui+=elm.menu; // add after setting '_owner' because it may affect level in children array
  48. }
  49. return T;
  50. }
  51. MenuBar& MenuBar::create(C MenuBar &src)
  52. {
  53. if(this!=&src)
  54. {
  55. if(!src.is())del();else
  56. {
  57. copyParams(src);
  58. _type =GO_MENU_BAR;
  59. _skin =src._skin;
  60. _alt =src._alt;
  61. _lit =src._lit;
  62. _push =src._push;
  63. _menu_prev=src._menu_prev;
  64. _elms.setNum(src.elms()); FREP(elms())
  65. {
  66. elm(i).create(src.elm(i));
  67. elm(i).menu._owner=this;
  68. }
  69. }
  70. }
  71. return T;
  72. }
  73. /******************************************************************************/
  74. void MenuBar::setElms()
  75. {
  76. if(GuiSkin *skin=getSkin())
  77. if(TextStyle *text_style=skin->menubar.text_style())
  78. {
  79. Flt x=0, h=rect().h(), padd=skin->menubar.text_padd*h;
  80. TextStyleParams ts=*text_style; ts.size=skin->menubar.text_size*h;
  81. FREP(elms())
  82. {
  83. Flt w=ts.textWidth(elm(i).display_name)+padd;
  84. elm(i).x=x;
  85. elm(i).w=w;
  86. if(!elm(i).hidden)x+=w;
  87. }
  88. }
  89. }
  90. MenuBar& MenuBar::rect(C Rect &rect)
  91. {
  92. if(T.rect()!=rect)
  93. {
  94. super::rect(rect);
  95. setElms();
  96. }
  97. return T;
  98. }
  99. Rect MenuBar::elmsRect()C
  100. {
  101. Rect r=rect(); r.max.x=r.min.x; if(elms())r.max.x+=_elms.last().x1();
  102. return r;
  103. }
  104. MenuBar& MenuBar::skin(C GuiSkinPtr &skin, Bool sub_objects)
  105. {
  106. T._skin=skin;
  107. if(sub_objects)REPAO(_elms).menu.skin(skin, true);
  108. return T;
  109. }
  110. void MenuBar::parentClientRectChanged(C Rect *old_client, C Rect *new_client)
  111. {
  112. if(new_client)
  113. if(GuiSkin *skin=getSkin())
  114. rect(Rect_LU(new_client->min.x, new_client->max.y, new_client->w(), skin->menubar.bar_height));
  115. }
  116. /******************************************************************************/
  117. void MenuBar::operator()(C Str &command, Bool on, SET_MODE mode)
  118. {
  119. CChar *start=_GetStart(command);
  120. if( Is(start))REP(elms())if(Equal(elm(i).name, start)){elm(i).menu(_GetStartNot(command), on, mode); break;}
  121. }
  122. Bool MenuBar::operator()(C Str &command)C
  123. {
  124. CChar *start=_GetStart(command);
  125. if( Is(start))REP(elms())if(Equal(elm(i).name, start))return elm(i).menu(_GetStartNot(command));
  126. return false;
  127. }
  128. Bool MenuBar::exists(C Str &command)C
  129. {
  130. CChar *start=_GetStart(command);
  131. if( Is(start))REP(elms())if(Equal(elm(i).name, start))
  132. {
  133. start=_GetStartNot(command);
  134. if(Is(start))return elm(i).menu.exists(start);
  135. return true;
  136. }
  137. return false;
  138. }
  139. /******************************************************************************/
  140. MenuBar& MenuBar::setCommand(C Str &command, Bool visible, Bool enabled)
  141. {
  142. CChar *start=_GetStart(command);
  143. if( Is(start))REP(elms())if(Equal(elm(i).name, start))
  144. {
  145. start=_GetStartNot(command);
  146. if(!Is(start))
  147. {
  148. if(enabled==elm(i).menu.disabled())elm(i).menu.disabled(!elm(i).menu.disabled());
  149. if(visible==elm(i).hidden)
  150. {
  151. elm(i).hidden^=1;
  152. if(elm(i).menu.contains(Gui.menu()))activate();
  153. setElms();
  154. }
  155. }
  156. break;
  157. }
  158. return T;
  159. }
  160. /******************************************************************************/
  161. static void Activate(MenuBar &menu, MenuBar::Elm &elm, C GuiPC &gpc)
  162. {
  163. Vec2 pos(menu.rect().min.x+elm.x+gpc.offset.x-elm.menu.paddingL(), menu.rect().min.y+gpc.offset.y);
  164. Rect screen_rect(0, -D.h(), 0, D.h());
  165. Flt h_below=(Rect_LU(0, pos.y , 0, elm.menu.rect().h())&screen_rect).h(), // visible height when below the MenuBar
  166. h_above=(Rect_LD(0, pos.y+menu.rect().h(), 0, elm.menu.rect().h())&screen_rect).h(); // visible height when above the MenuBar
  167. elm.menu.pos((h_above>h_below+EPS) ? pos+Vec2(0, menu.rect().h()+elm.menu.rect().h()) : pos).activate(); // select position according to which visible height is bigger, use EPS to more often place the Menu below
  168. }
  169. void MenuBar::update(C GuiPC &gpc)
  170. {
  171. if(enabled() && gpc.enabled)
  172. {
  173. // activate
  174. if((Kb.bp(KB_LALT) || Kb.bp(KB_MENU)) // if menu key pressed this frame
  175. && visible() && gpc.visible // this MenuBar is visible
  176. && first(GO_WINDOW)==Gui.window() // it belongs to the focused window (this also works OK if there's no focused window and this MenuBar doesn't belong to any window)
  177. )_alt=true; // mark that alt is being pressed
  178. if(_alt) // if alt is being pressed
  179. {
  180. if(Kb.k.c
  181. ||(Kb.k.k && Kb.k.k!=KB_ALT && Kb.k.k!=KB_LALT && Kb.k.k!=KB_RALT && Kb.k.k!=KB_MENU)
  182. || Kb.ctrl() || Kb.shift() || Kb.win()
  183. || Kb.b(KB_FIND)
  184. || Ms._button[0] || Ms._button[1] || Ms._button[2]
  185. || !App.active() // if lost focus due to Alt-tab
  186. )_alt=false;else // if any action happened, then cancel activating
  187. if(Kb.br(KB_LALT) || Kb.br(KB_MENU)) // if menu key released
  188. {
  189. _alt=false; // finished
  190. if(_menu_prev>=0)deactivate();else // if already activated, then deactivate
  191. FREP(elms())if(!elm(i).hidden){_push=i; break;} // find first visible and push it
  192. }
  193. }
  194. // get highlight
  195. if(_push>=0)_lit=_push;else
  196. if(Gui.ms()!=this || (!Ms._action && _menu_prev>=0))_lit=_menu_prev;else
  197. {
  198. _lit=-1;
  199. Flt l=rect().min.x+gpc.offset.x,
  200. b=rect().min.y+gpc.offset.y,
  201. t=rect().max.y+gpc.offset.y;
  202. REP(elms())
  203. {
  204. Elm &e=elm(i);
  205. if( !e.hidden && !e.menu.disabled() && Ms.test(Rect(l+e.x, b, l+e.x1(), t))){_lit=i; goto found;}
  206. }
  207. if(Gui.ms()==this)_lit=_menu_prev;
  208. found:;
  209. }
  210. // activate menu
  211. if(_lit!=_menu_prev && _lit>=0)
  212. if(Ms.bp(0) || _menu_prev>=0 || _push>=0)
  213. {
  214. Elm &e=elm(_lit);
  215. if(Ms.bp(0))
  216. {
  217. e.menu.list.cur=-1;
  218. Ms.eat(0);
  219. }else
  220. {
  221. e.menu.list.cur=(e.menu.list.elms() ? 0 : -1);
  222. }
  223. Activate(T, e, gpc);
  224. }
  225. REPA(Touches)
  226. {
  227. Touch &touch=Touches[i];
  228. if(touch.guiObj()==this)
  229. {
  230. Flt l=rect().min.x+gpc.offset.x,
  231. b=rect().min.y+gpc.offset.y,
  232. t=rect().max.y+gpc.offset.y;
  233. REP(elms())
  234. {
  235. Elm &e=elm(i);
  236. if( !e.hidden && !e.menu.disabled() && Cuts(touch.pos(), Rect(l+e.x, b, l+e.x1(), t)))
  237. {
  238. if(touch.pd() && _menu_prev==i) // deselect
  239. {
  240. activate();
  241. }else
  242. if(touch.pd() || _menu_prev>=0) // if we just pushed or there was already selected
  243. {
  244. e.menu.list.cur=-1;
  245. Activate(T, e, gpc);
  246. }
  247. break;
  248. }
  249. }
  250. }
  251. }
  252. _push=-1;
  253. _menu_prev=-1;
  254. if(Gui.menu())REP(elms())if(elm(i).menu.contains(Gui.menu())){_menu_prev=i; break;}
  255. }
  256. }
  257. /******************************************************************************/
  258. void MenuBar::draw(C GuiPC &gpc)
  259. {
  260. if(visible() && gpc.visible)
  261. if(GuiSkin *skin=getSkin())
  262. {
  263. D.clip(gpc.clip);
  264. Rect rect=T.rect()+gpc.offset;
  265. if(skin->menubar.background )skin->menubar.background->draw(skin->menubar.background_color, TRANSPARENT, rect);else
  266. if(skin->menubar.background_color.a) rect.draw(skin->menubar.background_color);
  267. if(TextStyle *text_style=skin->menubar.text_style())
  268. {
  269. TextStyleParams ts=*text_style; ts.align.set(0, 0); ts.size=rect.h()*skin->menubar.text_size; Flt y=rect.centerY();
  270. FREP(elms())if(!elm(i).hidden)
  271. {
  272. Elm &e=elm(i);
  273. Flt x=rect.min.x+e.x;
  274. if(_lit==i)
  275. {
  276. Rect lit_rect(x, rect.min.y, x+e.w, rect.max.y);
  277. if(skin->menubar.highlight )skin->menubar.highlight->draw(skin->menubar.highlight_color, TRANSPARENT, lit_rect);else
  278. if(skin->menubar.highlight_color.a) lit_rect.draw(skin->menubar.highlight_color);
  279. }
  280. D.text(ts, x+e.w*0.5f, y, e.display_name);
  281. }
  282. }
  283. }
  284. }
  285. /******************************************************************************/
  286. }
  287. /******************************************************************************/