JSUI.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include <TurboBadger/tb_widgets.h>
  2. #include <Atomic/UI/UIEvents.h>
  3. #include <Atomic/UI/UIWidget.h>
  4. #include <Atomic/UI/UI.h>
  5. #include "JSVM.h"
  6. #include "JSUI.h"
  7. using namespace tb;
  8. namespace Atomic
  9. {
  10. JSUI::JSUI(Context* context) : Object(context)
  11. {
  12. ctx_ = JSVM::GetJSVM(nullptr)->GetJSContext();
  13. SubscribeToEvent(E_WIDGETEVENT, HANDLER(JSUI, HandleWidgetEvent));
  14. SubscribeToEvent(E_WIDGETLOADED, HANDLER(JSUI, HandleWidgetLoaded));
  15. }
  16. JSUI::~JSUI()
  17. {
  18. }
  19. void JSUI::GatherWidgets(tb::TBWidget* widget, PODVector<tb::TBWidget*>& widgets)
  20. {
  21. if (widget->GetID() != TBID())
  22. widgets.Push(widget);
  23. for (TBWidget *n = widget->GetFirstChild(); n; n = n->GetNext())
  24. {
  25. GatherWidgets(n, widgets);
  26. }
  27. }
  28. void JSUI::HandleWidgetLoaded(StringHash eventType, VariantMap& eventData)
  29. {
  30. using namespace WidgetLoaded;
  31. UIWidget* widget = static_cast<UIWidget*>(eventData[P_WIDGET].GetPtr());
  32. if (!widget)
  33. return;
  34. void* heapptr = widget->JSGetHeapPtr();
  35. if (!heapptr)
  36. return;
  37. // a loaded widget recursively gathers children which have id's and
  38. // stashes them in an internal array, so that they don't go out of scope
  39. // for instance var button = window.getWidgetByID("reveal");
  40. // if we didn't stash, any callback on button wouldn't work if button went out
  41. // of scope, which isn't expected behavior (in JS you would think the button is
  42. // in some way attached to the window object)
  43. TBWidget* tbwidget = widget->GetInternalWidget();
  44. assert(tbwidget);
  45. PODVector<TBWidget*> widgets;
  46. GatherWidgets(tbwidget, widgets);
  47. UI* ui = GetSubsystem<UI>();
  48. duk_push_heapptr(ctx_, heapptr);
  49. duk_push_array(ctx_);
  50. unsigned arrayCount = 0;
  51. for (unsigned i = 0; i < widgets.Size(); i++)
  52. {
  53. UIWidget* o = ui->WrapWidget(widgets.At(i));
  54. if (!o)
  55. continue;
  56. js_push_class_object_instance(ctx_, o);
  57. duk_put_prop_index(ctx_, -2, arrayCount++);
  58. }
  59. duk_put_prop_string(ctx_, -2, "__child_widgets");
  60. duk_pop(ctx_);
  61. }
  62. void JSUI::HandleWidgetEvent(StringHash eventType, VariantMap& eventData)
  63. {
  64. using namespace WidgetEvent;
  65. UIWidget* widget = static_cast<UIWidget*>(eventData[P_TARGET].GetPtr());
  66. if (!widget)
  67. return;
  68. void* heapptr = widget->JSGetHeapPtr();
  69. if (!heapptr)
  70. return;
  71. tb::EVENT_TYPE type = (tb::EVENT_TYPE) eventData[P_TYPE].GetUInt();
  72. if (type == tb::EVENT_TYPE_CLICK)
  73. {
  74. int top = duk_get_top(ctx_);
  75. duk_push_heapptr(ctx_, heapptr);
  76. duk_get_prop_string(ctx_, -1, "onClick");
  77. if (duk_is_callable(ctx_, -1)) {
  78. duk_call(ctx_, 0);
  79. }
  80. duk_pop_n(ctx_, 2);
  81. assert(top == duk_get_top(ctx_));
  82. return;
  83. }
  84. eventData[P_TYPE];
  85. eventData[P_X];
  86. eventData[P_Y];
  87. eventData[P_DELTAX];
  88. eventData[P_DELTAY];
  89. eventData[P_COUNT];
  90. eventData[P_KEY];
  91. eventData[P_SPECIALKEY];
  92. eventData[P_MODIFIERKEYS];
  93. eventData[P_ID];
  94. eventData[P_TOUCH];
  95. }
  96. }