#include "widget.h" #define Min(a, b) ((a) < (b) ? (a) : (b)) #define Max(a, b) ((a) > (b) ? (a) : (b)) uiTable* uiMakeTable(int rows, int cols, const char** header) { uiTable* table = UI_NEW(uiTable); *table = (uiTable){ .widget = (uiWidget){.type = uiTypeTable}, .rows = rows, .cols = cols, .widths = (cols > 0) ? calloc(cols, sizeof(int)) : 0, .header = header ? calloc(cols, sizeof(uiCell)) : 0, .cells = (rows * cols > 0) ? calloc(rows, sizeof(uiCell*)) : 0, .flags = {0}, }; if (header) { for (int col = 0; col < cols; ++col) { table->header[col].text = string_new(header[col]); } } return table; } void uiTableClear(uiTable* table) { assert(table); // Free row data. if (table->cells) { for (int row = 0; row < table->rows; ++row) { for (int col = 0; col < table->cols; ++col) { string_del(&table->cells[row][col].text); } free(table->cells[row]); } free(table->cells); table->cells = 0; } table->rows = 0; // Clear row widths. for (int i = 0; i < table->cols; ++i) { table->widths[i] = 0; } table->offset = 0; table->flags.vertical_overflow = 0; } void uiTableAddRow(uiTable* table, const char** row) { assert(table); table->rows++; uiCell** cells = realloc(table->cells, table->rows * sizeof(uiCell*)); ASSERT(cells); table->cells = cells; uiCell** pLastRow = TableGetLastRow(table); *pLastRow = calloc(table->cols, sizeof(uiCell)); ASSERT(*pLastRow); uiCell* lastRow = *pLastRow; for (int col = 0; col < table->cols; ++col) { lastRow[col].text = string_new(row[col]); } } void uiTableSet(uiTable* table, int row, int col, const char* text) { assert(table); assert(text); TableGetCellMut(table, row, col)->text = string_new(text); } const char* uiTableGet(const uiTable* table, int row, int col) { assert(table); return string_data(TableGetCell(table, row, col)->text); } void uiTableScroll(uiTable* table, int row) { assert(table); table->offset = Min(table->rows - table->num_visible_rows, Max(0, row)); SyncScrollbarToTable(table); } void SyncScrollbarToTable(uiTable* table) { assert(table); ScrollbarScroll( &table->scrollbar, (int)((double)table->offset / (double)table->rows * (double)table->height)); } void SyncTableToScrollbar(uiTable* table) { assert(table); table->offset = (int)((double)table->scrollbar.handle_y / (double)table->height * (double)table->rows); } const uiCell* TableGetCell(const uiTable* table, int row, int col) { assert(table); return &table->cells[row][col]; } uiCell* TableGetCellMut(uiTable* table, int row, int col) { assert(table); return (uiCell*)TableGetCell(table, row, col); } uiCell** TableGetLastRow(uiTable* table) { assert(table); assert(table->rows > 0); return &table->cells[table->rows - 1]; }