From 8cdfd577b4f7d70acddde353b600559010ea6d39 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Wed, 04 Aug 2021 19:06:24 -0400 Subject: tk: Add grid widget --- (limited to 'src/tk/grid.c') diff --git a/src/tk/grid.c b/src/tk/grid.c new file mode 100644 index 0000000..4f09928 --- /dev/null +++ b/src/tk/grid.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2021 P. J. McDermott + * + * This file is part of Maze Fight + * + * Maze Fight is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Maze Fight is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Maze Fight. If not, see . + */ + +#include +#include "errno.h" +#include +#include +#include "../tk.h" +#include "widget.h" + +struct mftk_grid { + struct mftk_widget parent; + int rows; + int cols; + struct mftk_widget **children; + int *children_x; + int *children_y; + int row_spacing; + int col_spacing; +}; + +static void +_mftk_grid_layout(struct mftk_widget *w) +{ + struct mftk_grid *g = (struct mftk_grid *) w; + int r; + int c; + int sz; + int max_sz; + + w->h = 0; + for (r = 0; r < g->rows; ++r) { + g->children_y[r] = w->h; + max_sz = 0; + for (c = 0; c < g->cols; ++c) { + mftk_widget_layout(g->children[r * g->cols + c]); + sz = g->children[r * g->cols + c]->h; + if (sz > max_sz) { + max_sz = sz; + } + } + if (r > 0) { + w->h += g->row_spacing; + } + w->h += max_sz; + } + + w->w = 0; + for (c = 0; c < g->cols; ++c) { + g->children_x[c] = w->w; + max_sz = 0; + for (r = 0; r < g->rows; ++r) { + sz = g->children[r * g->cols + c]->w; + if (sz > max_sz) { + max_sz = sz; + } + } + if (c > 0) { + w->w += g->col_spacing; + } + w->w += max_sz; + } +} + +static int +_mftk_grid_event(struct mftk_widget *w, SDL_Event *e) +{ + struct mftk_grid *g = (struct mftk_grid *) w; + + switch (e->type) { + case SDL_MOUSEBUTTONUP: + break; + default: + break; + } + + return 0; +} + +static int +_mftk_grid_render(struct mftk_widget *w, SDL_Renderer *renderer, int x, int y) +{ + struct mftk_grid *g = (struct mftk_grid *) w; + int e = 0; + int r; + int c; + + for (r = 0; r < g->rows; ++r) { + for (c = 0; c < g->cols; ++c) { + if (mftk_widget_render(g->children[r * g->cols + c], + renderer, + x + g->children_x[c], + y + g->children_y[r]) < 0) { + e = -1; + } + } + } + + return e; +} + +static void +_mftk_grid_destroy(struct mftk_widget *w) +{ + struct mftk_grid *g = (struct mftk_grid *) w; + int r; + int c; + + for (r = 0; r < g->rows; ++r) { + for (c = 0; c < g->cols; ++c) { + mftk_widget_destroy(&g->children[r * g->cols + c]); + } + } + + free(g->children); + free(g->children_x); + free(g->children_y); +} + +struct mftk_widget * +mftk_grid_new(int rows, int cols, int row_spacing, int col_spacing, ...) +{ + struct mftk_widget *w; + struct mftk_grid *g; + va_list ap; + int r; + int c; + + if ((w = mftk_widget_new(sizeof(*g))) == NULL) return NULL; + g = (struct mftk_grid *) w; + w->layout = &_mftk_grid_layout; + w->event = &_mftk_grid_event; + w->render = &_mftk_grid_render; + w->destroy = &_mftk_grid_destroy; + + g->children = calloc(rows * cols, sizeof(*g->children)); + if (g->children == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Couldn't create widget: %s", + strerror(errno)); + free(g); + return NULL; + } + g->children_x = calloc(cols, sizeof(*g->children_x)); + if (g->children_x == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Couldn't create widget: %s", + strerror(errno)); + free(g->children); + free(g); + return NULL; + } + g->children_y = calloc(rows, sizeof(*g->children_y)); + if (g->children_y == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Couldn't create widget: %s", + strerror(errno)); + free(g->children_x); + free(g->children); + free(g); + return NULL; + } + + g->rows = rows; + g->cols = cols; + g->row_spacing = row_spacing; + g->col_spacing = col_spacing; + + va_start(ap, col_spacing); + for (r = 0; r < g->rows; ++r) { + for (c = 0; c < g->cols; ++c) { + g->children[r * g->cols + c] = va_arg(ap, + struct mftk_widget *); + } + } + va_end(ap); + + return w; +} -- cgit v0.9.1