JSUIAPI.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  2. // Please see LICENSE.md in repository root for license information
  3. // https://github.com/AtomicGameEngine/AtomicGameEngine
  4. #include <TurboBadger/tb_window.h>
  5. #include "JSUIAPI.h"
  6. #include "JSVM.h"
  7. #include <Atomic/UI/UI.h>
  8. #include <Atomic/UI/UISelectItem.h>
  9. #include <Atomic/UI/UIMenuWindow.h>
  10. #include <Atomic/UI/UIButton.h>
  11. #include <Atomic/UI/UIWindow.h>
  12. namespace Atomic
  13. {
  14. static int UIButton_Popup(duk_context* ctx)
  15. {
  16. if (!duk_is_object(ctx, 0))
  17. {
  18. duk_push_string(ctx, "UIButton.popup first argument must be an object");
  19. duk_throw(ctx);
  20. }
  21. if (!duk_is_callable(ctx, 1))
  22. {
  23. duk_push_string(ctx, "UIButton.popup second argument must be callable");
  24. duk_throw(ctx);
  25. }
  26. JSVM* vm = JSVM::GetJSVM(ctx);
  27. duk_enum(ctx, 0, DUK_ENUM_OWN_PROPERTIES_ONLY);
  28. UISelectItemSource* source = new UISelectItemSource(vm->GetContext());
  29. while (duk_next(ctx, -1, 0)) {
  30. String key = duk_get_string(ctx, -1);
  31. duk_get_prop(ctx, 0);
  32. if (duk_is_array(ctx, -1))
  33. {
  34. // need to support this, for skin image, etc
  35. assert(0);
  36. }
  37. else if (duk_is_string(ctx, -1))
  38. {
  39. // id
  40. String id = duk_get_string(ctx, -1);
  41. source->AddItem(new UISelectItem(vm->GetContext(), key, id));
  42. }
  43. else
  44. {
  45. duk_push_string(ctx, "UIButton.popup data object key is not an array or string");
  46. duk_throw(ctx);
  47. }
  48. duk_pop(ctx); // pop key value
  49. }
  50. duk_pop(ctx); // pop enum object
  51. duk_push_this(ctx);
  52. duk_dup(ctx, 1);
  53. duk_put_prop_string(ctx, -2, "__popup_menu_callback");
  54. UIButton* button = js_to_class_instance<UIButton>(ctx, -1, 0);
  55. UIMenuWindow* menuWindow = new UIMenuWindow(vm->GetContext(), button, "__popup-menu");
  56. menuWindow->Show(source);
  57. duk_pop(ctx);
  58. return 0;
  59. }
  60. int UIWindow_GetResizeToFitContentRect(duk_context* ctx)
  61. {
  62. duk_push_this(ctx);
  63. UIWindow* window = js_to_class_instance<UIWindow>(ctx, -1, 0);
  64. duk_pop(ctx);
  65. tb::TBWindow* tbwindow = (tb::TBWindow*) window->GetInternalWidget();
  66. tb::TBRect rect = tbwindow->GetResizeToFitContentRect();
  67. duk_push_object(ctx);
  68. duk_push_number(ctx, rect.x);
  69. duk_put_prop_string(ctx, -2, "x");
  70. duk_push_number(ctx, rect.y);
  71. duk_put_prop_string(ctx, -2, "y");
  72. duk_push_number(ctx, rect.w);
  73. duk_put_prop_string(ctx, -2, "width");
  74. duk_push_number(ctx, rect.h);
  75. duk_put_prop_string(ctx, -2, "height");
  76. return 1;
  77. }
  78. int UI_DebugGetUIKeepAliveCount(duk_context* ctx)
  79. {
  80. duk_push_global_stash(ctx);
  81. duk_get_prop_string(ctx, -1, "__jsui_widgetkeepalive");
  82. duk_enum(ctx, -1, DUK_ENUM_OWN_PROPERTIES_ONLY);
  83. double count = 0;
  84. while (duk_next(ctx, -1 , 0)) {
  85. duk_pop(ctx); /* pop_key */
  86. count++;
  87. }
  88. duk_pop_n(ctx, 3); /* pop enum object, keep alive object, and stash */
  89. duk_push_number(ctx, count);
  90. return 1;
  91. }
  92. int UI_DebugGetWrappedWidgetCount(duk_context* ctx)
  93. {
  94. JSVM* vm = JSVM::GetJSVM(ctx);
  95. UI* ui = vm->GetSubsystem<UI>();
  96. duk_push_number(ctx, (double) ui->DebugGetWrappedWidgetCount());
  97. return 1;
  98. }
  99. int UI_DebugShowSettingsWindow(duk_context* ctx)
  100. {
  101. UIWidget* widget = js_to_class_instance<UIWidget>(ctx, 0, 0);
  102. if (!widget)
  103. return 0;
  104. #ifdef TB_RUNTIME_DEBUG_INFO
  105. if (widget->GetInternalWidget())
  106. tb::ShowDebugInfoSettingsWindow(widget->GetInternalWidget());
  107. #endif
  108. return 0;
  109. }
  110. int UI_Init(duk_context* ctx)
  111. {
  112. JSVM* vm = JSVM::GetJSVM(ctx);
  113. UI* ui = vm->GetSubsystem<UI>();
  114. // TODO: take a config object
  115. ui->Initialize("DefaultUI/language/lng_en.tb.txt");
  116. ui->LoadSkin("DefaultUI/skin/skin.tb.txt", "Skin/skin.ui.txt");
  117. ui->AddFont("DefaultUI/fonts/vera.ttf", "Vera");
  118. ui->SetDefaultFont("Vera", 12);
  119. return 0;
  120. }
  121. void jsapi_init_ui(JSVM* vm)
  122. {
  123. duk_context* ctx = vm->GetJSContext();
  124. // UI object
  125. duk_get_global_string(ctx, "Atomic");
  126. duk_push_object(ctx);
  127. duk_push_c_function(ctx, UI_Init, DUK_VARARGS);
  128. duk_put_prop_string(ctx, -2, "__init");
  129. duk_push_c_function(ctx, UI_DebugGetWrappedWidgetCount, 0);
  130. duk_put_prop_string(ctx, -2, "debugGetWrappedWidgetCount");
  131. duk_push_c_function(ctx, UI_DebugGetUIKeepAliveCount, 0);
  132. duk_put_prop_string(ctx, -2, "debugGetUIKeepAliveCount");
  133. duk_push_c_function(ctx, UI_DebugShowSettingsWindow, 1);
  134. duk_put_prop_string(ctx, -2, "debugShowSettingsWindow");
  135. // Layout
  136. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_NONE);
  137. duk_put_prop_string(ctx, -2, "GRAVITY_NONE");
  138. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_LEFT);
  139. duk_put_prop_string(ctx, -2, "GRAVITY_LEFT");
  140. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_RIGHT);
  141. duk_put_prop_string(ctx, -2, "GRAVITY_RIGHT");
  142. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_TOP);
  143. duk_put_prop_string(ctx, -2, "GRAVITY_TOP");
  144. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_BOTTOM);
  145. duk_put_prop_string(ctx, -2, "GRAVITY_BOTTOM");
  146. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_LEFT_RIGHT);
  147. duk_put_prop_string(ctx, -2, "GRAVITY_LEFT_RIGHT");
  148. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_TOP_BOTTOM);
  149. duk_put_prop_string(ctx, -2, "GRAVITY_TOP_BOTTOM");
  150. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_ALL);
  151. duk_put_prop_string(ctx, -2, "GRAVITY_ALL");
  152. duk_push_number(ctx, (double) tb::WIDGET_GRAVITY_DEFAULT);
  153. duk_put_prop_string(ctx, -2, "GRAVITY_DEFAULT");
  154. duk_push_number(ctx, (double) tb::AXIS_X);
  155. duk_put_prop_string(ctx, -2, "AXIS_X");
  156. duk_push_number(ctx, (double) tb::AXIS_Y);
  157. duk_put_prop_string(ctx, -2, "AXIS_Y");
  158. duk_push_number(ctx, (double) tb::LAYOUT_SIZE_GRAVITY);
  159. duk_put_prop_string(ctx, -2, "LAYOUT_SIZE_GRAVITY");
  160. duk_push_number(ctx, (double) tb::LAYOUT_SIZE_PREFERRED);
  161. duk_put_prop_string(ctx, -2, "LAYOUT_SIZE_PREFERRED");
  162. duk_push_number(ctx, (double) tb::LAYOUT_SIZE_AVAILABLE);
  163. duk_put_prop_string(ctx, -2, "LAYOUT_SIZE_AVAILABLE");
  164. duk_push_number(ctx, (double) tb::LAYOUT_DISTRIBUTION_PREFERRED);
  165. duk_put_prop_string(ctx, -2, "LAYOUT_DISTRIBUTION_PREFERRED");
  166. duk_push_number(ctx, (double) tb::LAYOUT_DISTRIBUTION_AVAILABLE);
  167. duk_put_prop_string(ctx, -2, "LAYOUT_DISTRIBUTION_AVAILABLE");
  168. duk_push_number(ctx, (double) tb::LAYOUT_DISTRIBUTION_GRAVITY);
  169. duk_put_prop_string(ctx, -2, "LAYOUT_DISTRIBUTION_GRAVITY");
  170. duk_push_number(ctx, (double) tb::LAYOUT_POSITION_CENTER);
  171. duk_put_prop_string(ctx, -2, "LAYOUT_POSITION_CENTER");
  172. duk_push_number(ctx, (double) tb::LAYOUT_POSITION_LEFT_TOP);
  173. duk_put_prop_string(ctx, -2, "LAYOUT_POSITION_LEFT_TOP");
  174. duk_push_number(ctx, (double) tb::LAYOUT_POSITION_RIGHT_BOTTOM);
  175. duk_put_prop_string(ctx, -2, "LAYOUT_POSITION_RIGHT_BOTTOM");
  176. duk_push_number(ctx, (double) tb::LAYOUT_POSITION_GRAVITY);
  177. duk_put_prop_string(ctx, -2, "LAYOUT_POSITION_GRAVITY");
  178. duk_push_number(ctx, (double) tb::LAYOUT_DISTRIBUTION_POSITION_CENTER);
  179. duk_put_prop_string(ctx, -2, "LAYOUT_DISTRIBUTION_POSITION_CENTER");
  180. duk_push_number(ctx, (double) tb::LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP);
  181. duk_put_prop_string(ctx, -2, "LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP");
  182. duk_push_number(ctx, (double) tb::LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM);
  183. duk_put_prop_string(ctx, -2, "LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM");
  184. // Window Settings
  185. duk_push_number(ctx, (double) tb::WINDOW_SETTINGS_NONE);
  186. duk_put_prop_string(ctx, -2, "WINDOW_SETTINGS_NONE");
  187. duk_push_number(ctx, (double) tb::WINDOW_SETTINGS_TITLEBAR);
  188. duk_put_prop_string(ctx, -2, "WINDOW_SETTINGS_TITLEBAR");
  189. duk_push_number(ctx, (double) tb::WINDOW_SETTINGS_RESIZABLE);
  190. duk_put_prop_string(ctx, -2, "WINDOW_SETTINGS_RESIZABLE");
  191. duk_push_number(ctx, (double) tb::WINDOW_SETTINGS_CLOSE_BUTTON);
  192. duk_put_prop_string(ctx, -2, "WINDOW_SETTINGS_CLOSE_BUTTON");
  193. duk_push_number(ctx, (double) tb::WINDOW_SETTINGS_CAN_ACTIVATE);
  194. duk_put_prop_string(ctx, -2, "WINDOW_SETTINGS_CAN_ACTIVATE");
  195. duk_push_number(ctx, (double) tb::WINDOW_SETTINGS_DEFAULT);
  196. duk_put_prop_string(ctx, -2, "WINDOW_SETTINGS_DEFAULT");
  197. duk_push_number(ctx, (double) tb::WIDGET_STATE_NONE);
  198. duk_put_prop_string(ctx, -2, "WIDGET_STATE_NONE");
  199. duk_push_number(ctx, (double) tb::WIDGET_STATE_DISABLED);
  200. duk_put_prop_string(ctx, -2, "WIDGET_STATE_DISABLED");
  201. duk_push_number(ctx, (double) tb::WIDGET_STATE_FOCUSED);
  202. duk_put_prop_string(ctx, -2, "WIDGET_STATE_FOCUSED");
  203. duk_push_number(ctx, (double) tb::WIDGET_STATE_PRESSED);
  204. duk_put_prop_string(ctx, -2, "WIDGET_STATE_PRESSED");
  205. duk_push_number(ctx, (double) tb::WIDGET_STATE_SELECTED);
  206. duk_put_prop_string(ctx, -2, "WIDGET_STATE_SELECTED");
  207. duk_push_number(ctx, (double) tb::WIDGET_STATE_HOVERED);
  208. duk_put_prop_string(ctx, -2, "WIDGET_STATE_HOVERED");
  209. duk_push_number(ctx, (double) tb::WIDGET_STATE_ALL);
  210. duk_put_prop_string(ctx, -2, "WIDGET_STATE_ALL");
  211. duk_put_prop_string(ctx, -2, "UI");
  212. duk_pop(ctx);
  213. js_class_get_prototype(ctx, "UIButton");
  214. duk_push_c_function(ctx, UIButton_Popup, 2);
  215. duk_put_prop_string(ctx, -2, "popup");
  216. duk_pop(ctx);
  217. js_class_get_prototype(ctx, "UIWindow");
  218. duk_push_c_function(ctx, UIWindow_GetResizeToFitContentRect, 0);
  219. duk_put_prop_string(ctx, -2, "getResizeToFitContentRect");
  220. duk_pop(ctx);
  221. }
  222. }