Browse Source

Stash a widgets loaded widgets that have id for more natural object lifetime

Josh Engebretson 10 years ago
parent
commit
303ff2dcd8

+ 5 - 0
Source/Atomic/UI/UIEvents.h

@@ -43,6 +43,11 @@ EVENT(E_WIDGETEVENT, WidgetEvent)
     PARAM(P_TOUCH, Touch);               // bool
 }
 
+EVENT(E_WIDGETLOADED, WidgetLoaded)
+{
+    PARAM(P_WIDGET, Widget);             // UIWidget pointer
+}
+
 /// Mouse click in the UI.
 EVENT(E_UIMOUSECLICK, UIMouseClick)
 {

+ 6 - 1
Source/Atomic/UI/UIWidget.cpp

@@ -34,7 +34,12 @@ bool UIWidget::Load(const String& filename)
     UI* ui = GetSubsystem<UI>();
 
     if  (!ui->LoadResourceFile(widget_ , filename))
-        return false;
+        return false;    
+
+    VariantMap eventData;
+    eventData[WidgetLoaded::P_WIDGET] = this;
+    SendEvent(E_WIDGETLOADED, eventData);
+    return true;
 
     return true;
 }

+ 2 - 0
Source/Atomic/UI/UIWidget.h

@@ -34,6 +34,8 @@ public:
 
     void AddChild(UIWidget* child);
 
+    tb::TBWidget* GetInternalWidget() { return widget_; }
+
 protected:
 
     void ConvertEvent(UIWidget* target, const tb::TBWidgetEvent &ev, VariantMap& data);

+ 65 - 0
Source/AtomicJS/Javascript/JSUI.cpp

@@ -2,9 +2,12 @@
 
 #include <Atomic/UI/UIEvents.h>
 #include <Atomic/UI/UIWidget.h>
+#include <Atomic/UI/UI.h>
 #include "JSVM.h"
 #include "JSUI.h"
 
+using namespace tb;
+
 namespace Atomic
 {
 
@@ -12,6 +15,7 @@ JSUI::JSUI(Context* context) : Object(context)
 {
     ctx_ = JSVM::GetJSVM(nullptr)->GetJSContext();
     SubscribeToEvent(E_WIDGETEVENT, HANDLER(JSUI, HandleWidgetEvent));
+    SubscribeToEvent(E_WIDGETLOADED, HANDLER(JSUI, HandleWidgetLoaded));
 }
 
 JSUI::~JSUI()
@@ -19,6 +23,67 @@ JSUI::~JSUI()
 
 }
 
+void JSUI::GatherWidgets(tb::TBWidget* widget, PODVector<tb::TBWidget*>& widgets)
+{
+    if (widget->GetID() != TBID())
+        widgets.Push(widget);
+
+    for (TBWidget *n = widget->GetFirstChild(); n; n = n->GetNext())
+    {
+        GatherWidgets(n, widgets);
+    }
+
+}
+
+void JSUI::HandleWidgetLoaded(StringHash eventType, VariantMap& eventData)
+{
+    using namespace WidgetLoaded;
+
+    UIWidget* widget = static_cast<UIWidget*>(eventData[P_WIDGET].GetPtr());
+    if (!widget)
+        return;
+
+    void* heapptr = widget->JSGetHeapPtr();
+
+    if (!heapptr)
+        return;
+
+    // a loaded widget recursively gathers children which have id's and
+    // stashes them in an internal array, so that they don't go out of scope
+    // for instance var button = window.getWidgetByID("reveal");
+    // if we didn't stash, any callback on button wouldn't work if button went out
+    // of scope, which isn't expected behavior (in JS you would think the button is
+    // in some way attached to the window object)
+
+    TBWidget* tbwidget = widget->GetInternalWidget();
+    assert(tbwidget);
+
+    PODVector<TBWidget*> widgets;
+    GatherWidgets(tbwidget, widgets);
+
+    UI* ui = GetSubsystem<UI>();
+
+    duk_push_heapptr(ctx_, heapptr);
+    duk_push_array(ctx_);
+
+    unsigned arrayCount = 0;
+    for (unsigned i = 0; i < widgets.Size(); i++)
+    {
+        UIWidget* o =  ui->WrapWidget(widgets.At(i));
+
+        if (!o)
+            continue;
+
+        js_push_class_object_instance(ctx_, o);
+
+        duk_put_prop_index(ctx_, -2, arrayCount++);
+    }
+
+    duk_put_prop_string(ctx_, -2, "__child_widgets");
+    duk_pop(ctx_);
+
+}
+
 void JSUI::HandleWidgetEvent(StringHash eventType, VariantMap& eventData)
 {
     using namespace WidgetEvent;

+ 7 - 0
Source/AtomicJS/Javascript/JSUI.h

@@ -4,6 +4,11 @@
 #include <Duktape/duktape.h>
 #include <Atomic/Core/Object.h>
 
+namespace tb
+{
+class TBWidget;
+}
+
 namespace Atomic
 {
 
@@ -21,7 +26,9 @@ private:
     duk_context* ctx_;
 
     void HandleWidgetEvent(StringHash eventType, VariantMap& eventData);
+    void HandleWidgetLoaded(StringHash eventType, VariantMap& eventData);
 
+    void GatherWidgets(tb::TBWidget* widget, PODVector<tb::TBWidget*>& widgets);
 
 };