ltk

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/ltk.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ltk.git (over tor)
Log | Files | Refs | README | LICENSE

grid.c (5626B)


      1 /*
      2  * Copyright (c) 2016-2024 lumidify <nobody@lumidify.org>
      3  *
      4  * Permission to use, copy, modify, and/or distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include "ltkd.h"
     18 #include "widget.h"
     19 #include "cmd.h"
     20 
     21 #include <ltk/ltk.h>
     22 #include <ltk/grid.h>
     23 
     24 /* grid <grid id> add <widget id> <row> <column> <row_span> <column_span> [sticky] */
     25 static int
     26 ltkd_grid_cmd_add(
     27     ltk_window *window,
     28     ltkd_widget *widget,
     29     ltkd_cmd_token *tokens,
     30     size_t num_tokens,
     31     ltkd_error *err) {
     32 	(void)window;
     33 	ltk_grid *grid = LTK_CAST_GRID(widget->widget);
     34 	ltkd_cmdarg_parseinfo cmd[] = {
     35 		{.type = CMDARG_WIDGET, .widget_type = LTK_WIDGET_UNKNOWN, .optional = 0},
     36 		{.type = CMDARG_INT, .min = 0, .max = grid->rows - 1, .optional = 0},
     37 		{.type = CMDARG_INT, .min = 0, .max = grid->columns - 1, .optional = 0},
     38 		{.type = CMDARG_INT, .min = 0, .max = grid->rows, .optional = 0},
     39 		{.type = CMDARG_INT, .min = 0, .max = grid->columns, .optional = 0},
     40 		{.type = CMDARG_STICKY, .optional = 1},
     41 	};
     42 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
     43 		return 1;
     44 	int row = cmd[1].val.i, col = cmd[2].val.i;
     45 	int rowspan = cmd[3].val.i, colspan = cmd[4].val.i;
     46 	if (row + rowspan > grid->rows) {
     47 		err->type = ERR_GRID_INVALID_POSITION;
     48 		err->arg = 1;
     49 	}
     50 	if (col + colspan > grid->columns) {
     51 		err->type = ERR_GRID_INVALID_POSITION;
     52 		err->arg = 2;
     53 	}
     54 	/* FIXME: better error reporting for invalid grid position */
     55 	/* FIXME: check if recalculation deals properly with rowspan/columnspan
     56 	   that goes over the edge of the grid */
     57 	if (ltk_grid_add(
     58 	    grid, cmd[0].val.widget->widget,
     59 	    row, col, rowspan, colspan,
     60 	    cmd[5].initialized ? cmd[5].val.sticky : 0)) {
     61 		err->type = ERR_WIDGET_IN_CONTAINER;
     62 		err->arg = 0;
     63 		return 1;
     64 	}
     65 	return 0;
     66 }
     67 
     68 /* grid <grid id> remove <widget id> */
     69 static int
     70 ltkd_grid_cmd_ungrid(
     71     ltk_window *window,
     72     ltkd_widget *widget,
     73     ltkd_cmd_token *tokens,
     74     size_t num_tokens,
     75     ltkd_error *err) {
     76 	(void)window;
     77 	ltk_grid *grid = LTK_CAST_GRID(widget->widget);
     78 	ltkd_cmdarg_parseinfo cmd[] = {
     79 		{.type = CMDARG_WIDGET, .widget_type = LTK_WIDGET_UNKNOWN, .optional = 0}
     80 	};
     81 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
     82 		return 1;
     83 	if (ltk_grid_remove(grid, cmd[0].val.widget->widget)) {
     84 		err->type = ERR_WIDGET_NOT_IN_CONTAINER;
     85 		err->arg = 0;
     86 		return 1;
     87 	}
     88 	return 0;
     89 }
     90 
     91 /* FIXME: max size of 64 is completely arbitrary! */
     92 /* grid <grid id> create <rows> <columns> */
     93 static int
     94 ltkd_grid_cmd_create(
     95     ltk_window *window,
     96     ltkd_widget *widget_unneeded,
     97     ltkd_cmd_token *tokens,
     98     size_t num_tokens,
     99     ltkd_error *err) {
    100 	(void)widget_unneeded;
    101 	ltkd_cmdarg_parseinfo cmd[] = {
    102 		{.type = CMDARG_IGNORE, .optional = 0},
    103 		{.type = CMDARG_STRING, .optional = 0},
    104 		{.type = CMDARG_IGNORE, .optional = 0},
    105 		{.type = CMDARG_INT, .min = 0, .max = 64, .optional = 0},
    106 		{.type = CMDARG_INT, .min = 0, .max = 64, .optional = 0},
    107 	};
    108 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
    109 		return 1;
    110 	ltk_grid *grid = ltk_grid_create(window, cmd[3].val.i, cmd[4].val.i);
    111 	if (!ltkd_widget_create(LTK_CAST_WIDGET(grid), cmd[1].val.str, NULL, 0, err)) {
    112 		ltk_widget_destroy(LTK_CAST_WIDGET(grid), 1);
    113 		err->arg = 1;
    114 		return 1;
    115 	}
    116 
    117 	return 0;
    118 }
    119 
    120 /* FIXME: 64 is completely arbitrary */
    121 /* grid <grid id> set-row-weight <row> <weight> */
    122 static int
    123 ltkd_grid_cmd_set_row_weight(
    124     ltk_window *window,
    125     ltkd_widget *widget,
    126     ltkd_cmd_token *tokens,
    127     size_t num_tokens,
    128     ltkd_error *err) {
    129 	(void)window;
    130 	ltk_grid *grid = LTK_CAST_GRID(widget->widget);
    131 	ltkd_cmdarg_parseinfo cmd[] = {
    132 		{.type = CMDARG_INT, .min = 0, .max = grid->rows - 1, .optional = 0},
    133 		{.type = CMDARG_INT, .min = 0, .max = 64, .optional = 0},
    134 	};
    135 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
    136 		return 1;
    137 	ltk_grid_set_row_weight(grid, cmd[0].val.i, cmd[1].val.i);
    138 
    139 	return 0;
    140 }
    141 
    142 
    143 /* FIXME: 64 is completely arbitrary */
    144 /* FIXME: check for overflows in various grid calculations (at least when larger values are allowed) */
    145 /* grid <grid id> set-column-weight <column> <weight> */
    146 static int
    147 ltkd_grid_cmd_set_column_weight(
    148     ltk_window *window,
    149     ltkd_widget *widget,
    150     ltkd_cmd_token *tokens,
    151     size_t num_tokens,
    152     ltkd_error *err) {
    153 	(void)window;
    154 	ltk_grid *grid = LTK_CAST_GRID(widget->widget);
    155 	ltkd_cmdarg_parseinfo cmd[] = {
    156 		{.type = CMDARG_INT, .min = 0, .max = grid->columns - 1, .optional = 0},
    157 		{.type = CMDARG_INT, .min = 0, .max = 64, .optional = 0},
    158 	};
    159 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
    160 		return 1;
    161 	ltk_grid_set_column_weight(grid, cmd[0].val.i, cmd[1].val.i);
    162 
    163 	return 0;
    164 }
    165 
    166 static ltkd_cmd_info grid_cmds[] = {
    167 	{"add", &ltkd_grid_cmd_add, 0},
    168 	{"create", &ltkd_grid_cmd_create, 1},
    169 	{"remove", &ltkd_grid_cmd_ungrid, 0},
    170 	{"set-column-weight", &ltkd_grid_cmd_set_column_weight, 0},
    171 	{"set-row-weight", &ltkd_grid_cmd_set_row_weight, 0},
    172 };
    173 
    174 GEN_CMD_HELPERS(ltkd_grid_cmd, LTK_WIDGET_GRID, grid_cmds)