File RadioButtonWidget.c
File List > engine > src > gameframework > layers > UI > widgets > RadioButtonWidget.c
Go to the documentation of this file
#include "RadioButtonWidget.h"
#include "Widget.h"
#include "XMLUIGameLayer.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "Atlas.h"
#include "AssertLib.h"
#include "TextWidget.h"
#include "StaticWidget.h"
#include "RadioGroupWidget.h"
#include "DataNode.h"
#include "Log.h"
#ifndef max
#define max(a,b) (a>b?a:b)
#endif
enum RadioBtnPlacement
{
RBP_Left,
RBP_Right,
RBP_Above,
RBP_Below
};
struct RadioButtonData
{
struct TextWidgetData textWidgetData;
struct StaticWidgetData selectedRadioStatic;
struct StaticWidgetData unSelectedRadioStatic;
enum RadioBtnPlacement btnPlacementRelativeToText;
float buttonDistanceFromText;
bool bSelected;
};
static float GetBtnW(struct RadioButtonData* pData)
{
AtlasSprite* pAtlasSprite = At_GetSprite(pData->bSelected ? pData->selectedRadioStatic.sprite : pData->unSelectedRadioStatic.sprite,
pData->bSelected ? pData->selectedRadioStatic.atlas : pData->unSelectedRadioStatic.atlas);
return pAtlasSprite->widthPx;
}
static float GetBtnH(struct RadioButtonData* pData)
{
AtlasSprite* pAtlasSprite = At_GetSprite(pData->bSelected ? pData->selectedRadioStatic.sprite : pData->unSelectedRadioStatic.sprite,
pData->bSelected ? pData->selectedRadioStatic.atlas : pData->unSelectedRadioStatic.atlas);
return pAtlasSprite->heightPx;
}
static void GetSpriteAndAtlas(struct RadioButtonData* pData, hSprite* outSprite, hAtlas* outAtlas)
{
if (pData->bSelected)
{
*outAtlas = pData->selectedRadioStatic.atlas;
*outSprite = pData->selectedRadioStatic.sprite;
}
else
{
*outAtlas = pData->unSelectedRadioStatic.atlas;
*outSprite = pData->unSelectedRadioStatic.sprite;
}
}
static float GetWidth(struct UIWidget* pWidget, struct UIWidget* pParent)
{
struct RadioButtonData* pData = pWidget->pImplementationData;
hSprite sprite;
hAtlas atlas;
GetSpriteAndAtlas(pData, &sprite, &atlas);
AtlasSprite* pAtlasSprite = At_GetSprite(sprite, atlas);
float strW = Fo_StringWidth(pData->textWidgetData.atlas, pData->textWidgetData.font, pData->textWidgetData.content);
float btnW = GetBtnW(pData);
switch (pData->btnPlacementRelativeToText)
{
case RBP_Above:
case RBP_Below:
return max(strW, btnW)
+ pWidget->padding.paddingLeft
+ pWidget->padding.paddingRight;
break;
case RBP_Left:
case RBP_Right:
return
strW
+ pData->buttonDistanceFromText
+ btnW
+ pWidget->padding.paddingLeft
+ pWidget->padding.paddingRight;
break;
}
return 0.0f;
}
static float GetHeight(struct UIWidget* pWidget, struct UIWidget* pParent)
{
struct RadioButtonData* pData = pWidget->pImplementationData;
hSprite sprite;
hAtlas atlas;
GetSpriteAndAtlas(pData, &sprite, &atlas);
AtlasSprite* pAtlasSprite = At_GetSprite(sprite, atlas);
float strH = Fo_StringHeight(pData->textWidgetData.atlas, pData->textWidgetData.font, pData->textWidgetData.content);
float btnH = GetBtnH(pData);
switch (pData->btnPlacementRelativeToText)
{
case RBP_Above:
case RBP_Below:
return strH +
pData->buttonDistanceFromText +
btnH +
pWidget->padding.paddingTop +
pWidget->padding.paddingBottom;
break;
case RBP_Left:
case RBP_Right:
return max(strH, btnH) + pWidget->padding.paddingTop + pWidget->padding.paddingBottom;
break;
}
return 0.0f;
}
static void LayoutChildren(struct UIWidget* pWidget, struct UIWidget* pParent)
{
}
static void OnDestroy(struct UIWidget* pWidget)
{
struct RadioButtonData* pData = pWidget->pImplementationData;
StaticWidget_Destroy(&pData->selectedRadioStatic);
StaticWidget_Destroy(&pData->unSelectedRadioStatic);
TextWidget_Destroy(&pData->textWidgetData);
free(pWidget->pImplementationData);
}
static void* OnOutputVerts(struct UIWidget* pWidget, VECTOR(WidgetVertex) pOutVerts)
{
struct RadioButtonData* pData = pWidget->pImplementationData;
float startL = pWidget->left + pWidget->padding.paddingLeft;
float startT = pWidget->top + pWidget->padding.paddingTop;
struct WidgetPadding p;
memset(&p, 0, sizeof(struct WidgetPadding));
switch (pData->btnPlacementRelativeToText)
{
case RBP_Right:
{
pOutVerts = TextWidget_OutputVerts(startL, startT, &p, &pData->textWidgetData, pOutVerts);
float strW = Fo_StringWidth(pData->textWidgetData.atlas, pData->textWidgetData.font, pData->textWidgetData.content);
startL += strW + pData->buttonDistanceFromText;
struct StaticWidgetData* pStaticWidgetData = pData->bSelected ? &pData->selectedRadioStatic : &pData->unSelectedRadioStatic;
pOutVerts = StaticWidget_OnOutputVerts(pStaticWidgetData, startL, startT, &p, pOutVerts);
break;
}
case RBP_Left:
{
struct StaticWidgetData* pStaticWidgetData = pData->bSelected ? &pData->selectedRadioStatic : &pData->unSelectedRadioStatic;
pOutVerts = StaticWidget_OnOutputVerts(pStaticWidgetData, startL, startT, &p, pOutVerts);
float bw = GetBtnW(pData);
startL += bw + pData->buttonDistanceFromText;
pOutVerts = TextWidget_OutputVerts(startL, startT, &p, &pData->textWidgetData, pOutVerts);
break;
}
case RBP_Above:
{
float wWidth = GetWidth(pWidget, NULL);
float bw = GetBtnW(pData);
float bh = GetBtnH(pData);
float oldL = startL;
startL += (wWidth / 2.0f) - (bw / 2.0f);
struct StaticWidgetData* pStaticWidgetData = pData->bSelected ? &pData->selectedRadioStatic : &pData->unSelectedRadioStatic;
pOutVerts = StaticWidget_OnOutputVerts(pStaticWidgetData, startL, startT, &p, pOutVerts);
startL = oldL;
startT += bh + pData->buttonDistanceFromText;
pOutVerts = TextWidget_OutputVerts(startL, startT, &p, &pData->textWidgetData, pOutVerts);
break;
}
case RBP_Below:
{
pOutVerts = TextWidget_OutputVerts(startL, startT, &p, &pData->textWidgetData, pOutVerts);
float th = Fo_StringHeight(pData->textWidgetData.atlas, pData->textWidgetData.font, pData->textWidgetData.content);
startT += th;
float bw = GetBtnW(pData);
float wWidth = GetWidth(pWidget, NULL);
startL += (wWidth / 2.0f) - (bw / 2.0f);
startT += pData->buttonDistanceFromText;
struct StaticWidgetData* pStaticWidgetData = pData->bSelected ? &pData->selectedRadioStatic : &pData->unSelectedRadioStatic;
pOutVerts = StaticWidget_OnOutputVerts(pStaticWidgetData, startL, startT, &p, pOutVerts);
break;
}
}
return pOutVerts;
}
static void OnPropertyChanged(struct UIWidget* pThisWidget, struct WidgetPropertyBinding* pBinding)
{
}
static void MouseButtonDownCallback(struct UIWidget* pWidget, float x, float y, int btn)
{
RadioGroup_ChildSelected(pWidget->hParent, pWidget);
}
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 MakeDefaultRadioButtonData(struct RadioButtonData* pData, struct XMLUIData* pUILayerData)
{
pData->bSelected = false;
pData->btnPlacementRelativeToText = RBP_Right;
pData->buttonDistanceFromText = 10.0f;
pData->textWidgetData.atlas = pUILayerData->atlas;
pData->textWidgetData.content = malloc(strlen("option") + 1);
strcpy(pData->textWidgetData.content, "option");
pData->textWidgetData.fSizePts = 32.0f;
pData->textWidgetData.font = Fo_FindFont(pData->textWidgetData.atlas, "default", 32.0f);
pData->textWidgetData.r = 0.0f;
pData->textWidgetData.g = 0.0f;
pData->textWidgetData.b = 0.0f;
pData->textWidgetData.a = 1.0f;
pData->selectedRadioStatic.imageName = malloc(strlen("radioChecked") + 1);
strcpy(pData->selectedRadioStatic.imageName, "radioChecked");
pData->selectedRadioStatic.atlas = pUILayerData->atlas;
pData->selectedRadioStatic.scale.scaleX = 1.0f;
pData->selectedRadioStatic.scale.scaleY = 1.0f;
pData->selectedRadioStatic.sprite = At_FindSprite(pData->selectedRadioStatic.imageName, pData->selectedRadioStatic.atlas);
pData->unSelectedRadioStatic.imageName = malloc(strlen("radioUnchecked") + 1);
strcpy(pData->unSelectedRadioStatic.imageName, "radioUnchecked");
pData->unSelectedRadioStatic.atlas = pUILayerData->atlas;
pData->unSelectedRadioStatic.scale.scaleX = 1.0f;
pData->unSelectedRadioStatic.scale.scaleY = 1.0f;
pData->unSelectedRadioStatic.sprite = At_FindSprite(pData->unSelectedRadioStatic.imageName, pData->unSelectedRadioStatic.atlas);
}
static void RadioButtonWidget_MakeFromXML(struct DataNode* pDataNode, struct RadioButtonData* pData)
{
if(pDataNode->fnGetPropType(pDataNode, "btnPlacement") == DN_String)
{
if (pDataNode->fnStrCmp(pDataNode, "btnPlacement", "Left"))
{
pData->btnPlacementRelativeToText = RBP_Left;
}
else if (pDataNode->fnStrCmp(pDataNode, "btnPlacement", "Right"))
{
pData->btnPlacementRelativeToText = RBP_Right;
}
else if (pDataNode->fnStrCmp(pDataNode, "btnPlacement", "Above"))
{
pData->btnPlacementRelativeToText = RBP_Above;
}
else if (pDataNode->fnStrCmp(pDataNode, "btnPlacement", "Below"))
{
pData->btnPlacementRelativeToText = RBP_Below;
}
else
{
char* val = malloc(pDataNode->fnGetStrlen(pDataNode, "btnPlacement") + 1);
pDataNode->fnGetStrcpy(pDataNode, "btnPlacement", val);
Log_Error("Invlaid RadioBtnPlacement val '%s'", val);
free(val);
}
}
}
static void MakeWidgetIntoRadioButtonWidget(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->pImplementationData = malloc(sizeof(struct RadioButtonData));
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 RadioButtonData));
struct RadioButtonData* pData = pWidget->pImplementationData;
MakeDefaultRadioButtonData(pData, pUILayerData);
StaticWidget_MakeFromXML(&pData->selectedRadioStatic, pDataNode, pUILayerData);
StaticWidget_MakeFromXML(&pData->unSelectedRadioStatic, pDataNode, pUILayerData);
TextWidget_FromXML(pWidget, &pData->textWidgetData, pDataNode, pUILayerData);
RadioButtonWidget_MakeFromXML(pDataNode, pData);
}
HWidget RadioButtonWidgetNew(HWidget hParent, struct DataNode* pDataNode, struct XMLUIData* pUILayerData)
{
HWidget hWidget = UI_NewBlankWidget();
MakeWidgetIntoRadioButtonWidget(hWidget, pDataNode, pUILayerData);
return hWidget;
}
void RadioButton_SetSelected(HWidget hRadioButton, bool bSelected)
{
struct UIWidget* pWidget = UI_GetWidget(hRadioButton);
struct RadioButtonData* pData = pWidget->pImplementationData;
pData->bSelected = bSelected;
}