/*
* 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) {
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;
}
g->children_y[r] = w->h;
w->h += max_sz;
}
w->w = 0;
for (c = 0; c < g->cols; ++c) {
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;
}
g->children_x[c] = w->w;
w->w += max_sz;
}
}
static int
_mftk_grid_event(struct mftk_widget *w, SDL_Event *e, int x, int y)
{
struct mftk_grid *g = (struct mftk_grid *) w;
SDL_Point p;
SDL_Rect rect;
int r;
int c;
struct mftk_widget *child;
switch (e->type) {
case SDL_MOUSEBUTTONUP:
p.x = e->button.x;
p.y = e->button.y;
for (r = 0; r < g->rows; ++r) {
for (c = 0; c < g->cols; ++c) {
child = g->children[r * g->cols + c];
rect.x = x + g->children_x[c];
rect.y = y + g->children_y[r];
rect.w = child->w;
rect.h = child->h;
if (SDL_PointInRect(&p, &rect)
== SDL_TRUE) {
return mftk_widget_event(child,
e,
rect.x, rect.y);
}
}
}
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;
mftk_widget_init(w, g, grid);
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;
}