#include "widget.h" #include #include // ----------------------------------------------------------------------------- // Widget. #define UI_DEL(ppWidget) \ { \ assert(ppWidget); \ void* widget_ = *ppWidget; \ if (widget_) { \ free(widget_); \ *ppWidget = 0; \ } \ } uiWidgetType uiWidgetGetType(const uiWidget* widget) { assert(widget); return widget->type; } void DestroyWidget(uiWidget** ppWidget) { assert(ppWidget); uiWidget* widget = *ppWidget; if (widget) { list_foreach_mut(widget->children, child, { DestroyWidget(&child); }); } UI_DEL(ppWidget); } void WidgetSetParent(uiPtr child_, uiPtr parent_) { uiWidget* child = child_.widget; uiWidget* parent = parent_.widget; assert(child); assert(parent); if (!uiIsNullptr(child->parent)) { list_remove(child->parent.widget->children, child); } list_push(parent->children, child); child->parent = parent_; } // ----------------------------------------------------------------------------- // Widget pointers. uiPtr uiMakeButtonPtr(uiButton* button) { assert(button); return (uiPtr){.type = uiTypeButton, .button = button}; } uiPtr uiMakeFramePtr(uiFrame* frame) { assert(frame); return (uiPtr){.type = uiTypeFrame, .frame = frame}; } uiPtr uiMakeLabelPtr(uiLabel* label) { assert(label); return (uiPtr){.type = uiTypeLabel, .label = label}; } uiPtr uiMakeLayoutPtr(uiLayout* layout) { assert(layout); return (uiPtr){.type = uiTypeLayout, .layout = layout}; } uiPtr uiMakeTablePtr(uiTable* table) { assert(table); return (uiPtr){.type = uiTypeTable, .table = table}; } uiPtr uiMakeWidgetPtr(uiWidget* widget) { assert(widget); switch (widget->type) { case uiTypeButton: return uiMakeButtonPtr((uiButton*)widget); case uiTypeFrame: return uiMakeFramePtr((uiFrame*)widget); case uiTypeLabel: return uiMakeLabelPtr((uiLabel*)widget); case uiTypeLayout: return uiMakeLayoutPtr((uiLayout*)widget); case uiTypeTable: return uiMakeTablePtr((uiTable*)widget); default: ASSERT(false); break; } return (uiPtr){0}; } uiPtr uiNullptr(void) { return (uiPtr){0}; } bool uiIsNullptr(uiPtr ptr) { return ptr.widget == 0; } uiButton* uiGetButtonPtr(uiPtr ptr) { assert(ptr.type == uiTypeButton); assert(ptr.button); return ptr.button; } uiFrame* uiGetFramePtr(uiPtr ptr) { assert(ptr.type == uiTypeFrame); assert(ptr.frame); return ptr.frame; } uiLabel* uiGetLabelPtr(uiPtr ptr) { assert(ptr.type == uiTypeLabel); assert(ptr.label); return ptr.label; } uiLayout* uiGetLayoutPtr(uiPtr ptr) { assert(ptr.type == uiTypeLayout); assert(ptr.layout); return ptr.layout; } uiEdit* uiGetEditPtr(uiPtr ptr) { assert(ptr.type == uiTypeEdit); assert(ptr.edit); return ptr.edit; } uiTable* uiGetTablePtr(uiPtr ptr) { assert(ptr.type == uiTypeTable); assert(ptr.table); return ptr.table; } typedef struct PrintState { mstring pad; mstring rect; } PrintState; static void RectToString(uiRect rect, mstring* out) { assert(out); out->length = snprintf( out->str, sizeof(out->str), "rect{(x:%d, y:%d), (w:%d, h:%d)", rect.x, rect.y, rect.width, rect.height); } static void uiPrintRec(uiPtr ptr, PrintState* state) { if (uiIsNullptr(ptr)) { return; } RectToString(ptr.widget->rect, &state->rect); switch (ptr.type) { case uiTypeButton: { const uiButton* button = uiGetButtonPtr(ptr); printf( "%sbutton{rect=%s, text=\"%s\"}\n", mstring_cstr(&state->pad), mstring_cstr(&state->rect), string_cstr(&button->text)); break; } case uiTypeLabel: { const uiLabel* label = uiGetLabelPtr(ptr); printf( "%sbutton{rect=%s, text=\"%s\"}\n", mstring_cstr(&state->pad), mstring_cstr(&state->rect), string_cstr(&label->text)); break; } case uiTypeLayout: { const uiLayout* layout = uiGetLayoutPtr(ptr); const char* direction = ""; switch (layout->direction) { case uiHorizontal: direction = "horizontal"; break; case uiVertical: direction = "vertical"; break; } printf( "%s%s_layout{rect=%s}\n", mstring_cstr(&state->pad), direction, mstring_cstr(&state->rect)); break; } case uiTypeFrame: { printf( "%sframe{rect=%s}\n", mstring_cstr(&state->pad), mstring_cstr(&state->rect)); break; } case uiTypeTable: { const uiTable* table = uiGetTablePtr(ptr); printf( "%stable{rect=%s}\n", mstring_cstr(&state->pad), mstring_cstr(&state->rect)); break; } default: printf("%swidget\n", mstring_cstr(&state->pad)); break; } const mstring pad = state->pad; state->pad = mstring_concat(state->pad, mstring_make(" ")); list_foreach(ptr.widget->children, child, { uiPrintRec(uiMakeWidgetPtr(child), state); }); state->pad = pad; } void uiPrint(uiPtr ptr) { PrintState state = (PrintState){.pad = mstring_make_empty(), .rect = mstring_make_empty()}; uiPrintRec(ptr, &state); }