Browse Source

New UI Work

Josh Engebretson 10 years ago
parent
commit
5a835cbd35

+ 2 - 1
Source/Atomic/UI/UI.cpp

@@ -420,7 +420,7 @@ void UI::PruneUnreachableWidgets()
 
         delete toDelete;
 
-        // this will likely be flagged by valgrind as assessing invalid memory
+        // this will likely be flagged by valgrind as accessing invalid memory
         assert(!widgetWrap_.Contains(toDelete));
     }
 }
@@ -430,6 +430,7 @@ UIWidget* UI::WrapWidget(tb::TBWidget* widget)
     if (widgetWrap_.Contains(widget))
         return widgetWrap_[widget];
 
+    // this is order dependent as we're using IsOfType which also works if a base class
     if (widget->IsOfType<TBLayout>())
     {
         UILayout* layout = new UILayout(context_, false);

+ 0 - 1
Source/Atomic/UI/UIButton.cpp

@@ -22,7 +22,6 @@ UIButton::UIButton(Context* context, bool createWidget) : UIWidget(context, fals
 
 UIButton::~UIButton()
 {
-
 }
 
 bool UIButton::OnEvent(const tb::TBWidgetEvent &ev)

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

@@ -49,6 +49,11 @@ EVENT(E_WIDGETLOADED, WidgetLoaded)
     PARAM(P_WIDGET, Widget);             // UIWidget pointer
 }
 
+EVENT(E_WIDGETDELETED, WidgetDeleted)
+{
+    PARAM(P_WIDGET, Widget);             // UIWidget pointer
+}
+
 EVENT(E_POPUPMENUSELECT, PopupMenuSelect)
 {
     PARAM(P_BUTTON, Button);             // UIButton that created popup

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

@@ -91,6 +91,11 @@ void UIWidget::OnDelete()
     }
 
     widget_ = 0;
+
+    VariantMap eventData;
+    eventData[WidgetDeleted::P_WIDGET] = this;
+    SendEvent(E_WIDGETDELETED, eventData);
+
     ReleaseRef();
 }
 
@@ -100,6 +105,7 @@ void UIWidget::AddChild(UIWidget* child)
         return;
 
     widget_->AddChild(child->widget_);
+
 }
 
 void UIWidget::SetText(const String& text)
@@ -167,7 +173,6 @@ void UIWidget::RemoveChild(UIWidget* child)
         return;
 
     widget_->RemoveChild(childw);
-
 }
 
 

+ 10 - 0
Source/AtomicJS/Javascript/JSEvents.h

@@ -17,6 +17,16 @@ lineNumber	Rhino	Linenumber related to error source, inherited accessor
 stack	V8	Traceback as a multi-line human redable string, inherited accessor
 */
 
+EVENT(E_JSOBJECTADDED, ObjectAdded)
+{
+    PARAM(P_OBJECT, Object); // object
+}
+
+EVENT(E_JSOBJECTREMOVED, ObjectRemoved)
+{
+    PARAM(P_OBJECT, Object); // object
+}
+
 EVENT(E_JSERROR, JSError)
 {
     PARAM(P_ERRORNAME, ErrorName); // string

+ 62 - 1
Source/AtomicJS/Javascript/JSUI.cpp

@@ -17,10 +17,30 @@ JSUI::JSUI(Context* context) : Object(context),
     updateTime_(0.0f)
 {
     ctx_ = JSVM::GetJSVM(nullptr)->GetJSContext();
+
     SubscribeToEvent(E_UPDATE, HANDLER(JSUI, HandleUpdate));
+
+    SubscribeToEvent(E_JSOBJECTADDED, HANDLER(JSUI, HandleObjectAdded));
+
+    SubscribeToEvent(E_WIDGETDELETED, HANDLER(JSUI, HandleWidgetDeleted));
     SubscribeToEvent(E_WIDGETEVENT, HANDLER(JSUI, HandleWidgetEvent));
     SubscribeToEvent(E_WIDGETLOADED, HANDLER(JSUI, HandleWidgetLoaded));
     SubscribeToEvent(E_POPUPMENUSELECT, HANDLER(JSUI, HandlePopupMenuSelect));
+
+    duk_push_global_stash(ctx_);
+    duk_push_object(ctx_);
+    duk_put_prop_string(ctx_, -2, "__jsui_widgetkeepalive");
+    duk_pop(ctx_);
+
+    uiTypes_["UIWidget"] = true;
+    uiTypes_["UIButton"] = true;
+    uiTypes_["UIView"] = true;
+    uiTypes_["UIEditField"] = true;
+    uiTypes_["UITextField"] = true;
+    uiTypes_["UIImageWidget"] = true;
+    uiTypes_["UILayout"] = true;
+    uiTypes_["UIMenuWindow"] = true;
+    uiTypes_["UIWindow"] = true;
 }
 
 JSUI::~JSUI()
@@ -40,6 +60,48 @@ void JSUI::GatherWidgets(tb::TBWidget* widget, PODVector<tb::TBWidget*>& widgets
 
 }
 
+void JSUI::HandleObjectAdded(StringHash eventType, VariantMap& eventData)
+{
+    Object* o = static_cast<Object*>(eventData[ObjectAdded::P_OBJECT].GetPtr());
+
+    // for any UI type, we make sure it is kept alive
+    if (uiTypes_.Contains(o->GetType()))
+    {
+        assert(o->JSGetHeapPtr());
+
+        duk_push_global_stash(ctx_);
+        duk_get_prop_string(ctx_, -1, "__jsui_widgetkeepalive");
+        // can't use instance as key, as this coerces to [Object] for
+        // string property, pointer will be string representation of
+        // address, so, unique key
+        duk_push_pointer(ctx_, o);
+        duk_push_heapptr(ctx_, o->JSGetHeapPtr());
+        duk_put_prop(ctx_, -3);
+        duk_pop_2(ctx_);
+
+    }
+
+}
+
+void JSUI::HandleWidgetDeleted(StringHash eventType, VariantMap& eventData)
+{
+    UIWidget* widget = static_cast<UIWidget*>(eventData[WidgetDeleted::P_WIDGET].GetPtr());
+
+    if (!widget->JSGetHeapPtr())
+        return;
+
+    duk_push_global_stash(ctx_);
+    duk_get_prop_string(ctx_, -1, "__jsui_widgetkeepalive");
+    // can't use instance as key, as this coerces to [Object] for
+    // string property, pointer will be string representation of
+    // address, so, unique key
+    duk_push_pointer(ctx_, widget);
+    duk_push_null(ctx_);
+    duk_put_prop(ctx_, -3);
+    duk_pop_2(ctx_);
+
+}
+
 void JSUI::HandleUpdate(StringHash eventType, VariantMap& eventData)
 {
     float timeStep = eventData[Update::P_TIMESTEP].GetFloat();
@@ -54,7 +116,6 @@ void JSUI::HandleUpdate(StringHash eventType, VariantMap& eventData)
 }
 
 
-
 void JSUI::HandleWidgetLoaded(StringHash eventType, VariantMap& eventData)
 {
     using namespace WidgetLoaded;

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

@@ -28,13 +28,18 @@ private:
 
     void PushWidgetEventObject(VariantMap& eventData);
 
+    void HandleObjectAdded(StringHash eventType, VariantMap& eventData);
+
     void HandleUpdate(StringHash eventType, VariantMap& eventData);
     void HandleWidgetEvent(StringHash eventType, VariantMap& eventData);
+    void HandleWidgetDeleted(StringHash eventType, VariantMap& eventData);
     void HandleWidgetLoaded(StringHash eventType, VariantMap& eventData);
     void HandlePopupMenuSelect(StringHash eventType, VariantMap& eventData);
 
     void GatherWidgets(tb::TBWidget* widget, PODVector<tb::TBWidget*>& widgets);
 
+    HashMap<StringHash, bool> uiTypes_;
+
 };
 
 }

+ 10 - 0
Source/AtomicJS/Javascript/JSVM.h

@@ -11,6 +11,7 @@
 #include <Atomic/IO/Log.h>
 
 #include "JSAPI.h"
+#include "JSEvents.h"
 
 //#define JSVM_DEBUG
 
@@ -82,10 +83,16 @@ public:
             removedHeapPtr_.Erase(itr);
 #endif
 
+        objectAddedData_[ObjectAdded::P_OBJECT] = object;
+        SendEvent(E_JSOBJECTADDED, objectAddedData_);
+
     }
 
     inline void RemoveObject(RefCounted* object)
     {
+        objectRemovedData_[ObjectRemoved::P_OBJECT] = object;
+        SendEvent(E_JSOBJECTREMOVED, objectRemovedData_);
+
         void* heapptr = object->JSGetHeapPtr();
         assert(heapptr);
         object->JSSetHeapPtr(NULL);
@@ -158,6 +165,9 @@ private:
 
     SharedPtr<JSUI> ui_;
 
+    VariantMap objectAddedData_;
+    VariantMap objectRemovedData_;
+
     static JSVM* instance_;
 
 };