File RadioGroupWidget.c

File List > engine > src > gameframework > layers > UI > widgets > RadioGroupWidget.c

Go to the documentation of this file

#include "RadioGroupWidget.h"
#include "Widget.h"
#include "XMLUIGameLayer.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Atlas.h"
#include "AssertLib.h"
#include "StackPanelWidget.h"
#include "RadioButtonWidget.h"
#include "RootWidget.h"
#include "Scripting.h"
#include "DataNode.h"
#include "Log.h"

struct RadioGroupData
{
    struct StackPanelWidgetData data;
    int nSelectecedChild;
    HWidget rootWidget;
};

static float GetWidth(struct UIWidget* pWidget, struct UIWidget* pParent)
{
    struct StackPanelWidgetData* pData = &((struct RadioGroupData*)pWidget->pImplementationData)->data;
    return StackPanel_GetWidth(pWidget, pParent, pData);
}

static float GetHeight(struct UIWidget* pWidget, struct UIWidget* pParent)
{
    struct StackPanelWidgetData* pData = &((struct RadioGroupData*)pWidget->pImplementationData)->data;
    return StackPanel_GetHeight(pWidget, pParent, pData);
}

static void LayoutChildren(struct UIWidget* pWidget, struct UIWidget* pParent)
{
    struct StackPanelWidgetData* pData = &((struct RadioGroupData*)pWidget->pImplementationData)->data;
    float w = GetWidth(pWidget, pParent);
    float h = GetHeight(pWidget, pParent);
    StackPanel_LayoutChildren(pWidget, pParent, pData, w, h);
}

static void OnDestroy(struct UIWidget* pWidget)
{
    free(pWidget->pImplementationData);
}

static void* OnOutputVerts(struct UIWidget* pWidget, VECTOR(WidgetVertex) pOutVerts)
{
    pOutVerts = UI_Helper_OnOutputVerts(pWidget, pOutVerts);
    return pOutVerts;
}

static void OnWidgetInit(struct UIWidget* pWidget);

static void OnPropertyChanged(struct UIWidget* pThisWidget, struct WidgetPropertyBinding* pBinding)
{
    //selectedChild
    struct RadioGroupData* pData = pThisWidget->pImplementationData;
    if (strcmp(pBinding->boundPropertyName, "selectedChild") == 0)
    {
        char* fnName = UI_MakeBindingGetterFunctionName(pBinding->name);
        Sc_CallFuncInRegTableEntryTable(pThisWidget->scriptCallbacks.viewmodelTable, fnName, NULL, 0, 1);
        free(fnName);
        //pData->fVal = Sc_Float();
        pData->nSelectecedChild = Sc_Int();
        Sc_ResetStack();
        OnWidgetInit(pThisWidget);
    }

}


static void MouseButtonDownCallback(struct UIWidget* pWidget, float x, float y, int btn)
{
}

static void MouseButtonUpCallback(struct UIWidget* pWidget, float x, float y, int btn)
{

}

static void MouseLeaveCallback(struct UIWidget* pWidget, float x, float y)
{

}

static void MouseMoveCallback(struct UIWidget* pWidget, float x, float y)
{

}

static void OnWidgetInit(struct UIWidget* pWidget)
{
    struct RadioGroupData* pData = pWidget->pImplementationData;
    int i = 0;
    HWidget child = pWidget->hFirstChild;
    while (child != NULL_HWIDGET)
    {
        RadioButton_SetSelected(child, i == pData->nSelectecedChild);
        struct UIWidget* pChild = UI_GetWidget(child);
        child = pChild->hNext;
        i++;
    }
    SetRootWidgetIsDirty(pData->rootWidget, true);
}

static void ParseBindingEspressionAttribute(char* attribName, char* attribContent, struct UIWidget* pWidget, struct RadioGroupData* pData, struct XMLUIData* pUILayerData)
{
    if (strcmp(attribName, "selectedChild") == 0)
    {
        UI_AddIntPropertyBinding(pWidget, attribName, attribContent, &pData->nSelectecedChild, pUILayerData->hViewModel);
    }
    else
    {
        Log_Warning("invalid property binding: %s", attribContent);
    }
}

static void PopulateRadioGroupDataFromXML(struct UIWidget* pWidget, struct RadioGroupData* pData, struct DataNode* pDataNode, struct XMLUIData* pUILayerData)
{
    if (pDataNode->fnGetPropType(pDataNode, "selectedChild") == DN_String)
    {
        size_t len = pDataNode->fnGetStrlen(pDataNode, "selectedChild");
        if (!len)
        {
            Log_Warning("empty string");
            return;
        }
        char* val = malloc(len + 1);
        pDataNode->fnGetStrcpy(pDataNode, "selectedChild", val);
        if (UI_IsAttributeStringABindingExpression(val))
        {
            ParseBindingEspressionAttribute("selectedChild", val, pWidget, pData, pUILayerData);
        }
        else
        {
            pData->nSelectecedChild = atoi(val);
        }
        free(val);
    }
}

static void MakeWidgetIntoRadioGroupWidget(HWidget hWidget, struct DataNode* pDataNode, struct XMLUIData* pUILayerData)
{
    struct UIWidget* pWidget = UI_GetWidget(hWidget);
    pWidget->hNext = -1;
    pWidget->hPrev = -1;
    pWidget->hParent = -1;
    pWidget->hFirstChild = -1;
    pWidget->fnGetHeight = &GetHeight;
    pWidget->fnGetWidth = &GetWidth;
    pWidget->fnLayoutChildren = &LayoutChildren;
    pWidget->fnOnDestroy = &OnDestroy;
    pWidget->fnOutputVertices = &OnOutputVerts;
    pWidget->fnOnBoundPropertyChanged = &OnPropertyChanged;
    pWidget->fnOnWidgetInit = &OnWidgetInit;
    pWidget->pImplementationData = malloc(sizeof(struct RadioGroupData));

    pWidget->cCallbacks.Callbacks[WC_OnMouseDown].type = WC_OnMouseDown;
    pWidget->cCallbacks.Callbacks[WC_OnMouseDown].callback.mouseBtnFn = &MouseButtonDownCallback;

    pWidget->cCallbacks.Callbacks[WC_OnMouseUp].type = WC_OnMouseUp;
    pWidget->cCallbacks.Callbacks[WC_OnMouseUp].callback.mouseBtnFn = &MouseButtonUpCallback;

    pWidget->cCallbacks.Callbacks[WC_OnMouseLeave].type = WC_OnMouseLeave;
    pWidget->cCallbacks.Callbacks[WC_OnMouseLeave].callback.mousePosFn = &MouseLeaveCallback;

    pWidget->cCallbacks.Callbacks[WC_OnMouseMove].type = WC_OnMouseMove;
    pWidget->cCallbacks.Callbacks[WC_OnMouseMove].callback.mousePosFn = &MouseMoveCallback;

    memset(pWidget->pImplementationData, 0, sizeof(struct RadioGroupData));
    struct RadioGroupData* pData = pWidget->pImplementationData;
    pData->nSelectecedChild = 0;
    pData->rootWidget = pUILayerData->rootWidget;
    StackPanel_PopulateDataFromXML(pDataNode, &pData->data);
    PopulateRadioGroupDataFromXML(pWidget, pData, pDataNode, pUILayerData);
}

HWidget RadioGroupWidgetNew(HWidget hParent, struct DataNode* pDataNode, struct XMLUIData* pUILayerData)
{
    HWidget hWidget = UI_NewBlankWidget();
    MakeWidgetIntoRadioGroupWidget(hWidget, pDataNode, pUILayerData);
    return hWidget;
}

void RadioGroup_ChildSelected(HWidget hRadioGroup, struct UIWidget* pRadioButtonChild)
{
    struct UIWidget* pWidget = UI_GetWidget(hRadioGroup);
    struct RadioGroupData* pData = pWidget->pImplementationData;
    int i = 0;
    HWidget hChild = pWidget->hFirstChild;
    while (hChild != NULL_HWIDGET)
    {
        bool bSelected = false;
        struct UIWidget* pChild = UI_GetWidget(hChild);
        if (UI_GetWidget(hChild) == pRadioButtonChild)
        {
            bSelected = true;
            pData->nSelectecedChild = i;
            struct WidgetPropertyBinding* pBinding = UI_FindBinding(pWidget, "selectedChild");
            if (pBinding)
            {
                char* setterName = UI_MakeBindingSetterFunctionName(pBinding->name);
                struct ScriptCallArgument arg;
                arg.type = SCA_int;
                arg.val.i = pData->nSelectecedChild;
                Sc_CallFuncInRegTableEntryTable(pWidget->scriptCallbacks.viewmodelTable, setterName, &arg, 1, 0);
                free(setterName);
            }

        }

        RadioButton_SetSelected(hChild, bSelected);
        hChild = pChild->hNext;
        i++;
    }
    SetRootWidgetIsDirty(pData->rootWidget, true);
}