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 (5767B)


      1 /*
      2  * Copyright (c) 2016-2026 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_widget_id windowid,
     28     ltkd_widget *widget,
     29     ltkd_cmd_token *tokens,
     30     size_t num_tokens,
     31     ltkd_error *err) {
     32 	(void)windowid;
     33 	ltk_widget *gridw = ltk_get_widget_from_id(widget->ltkid);
     34 	ltk_grid *grid = LTK_CAST_GRID(gridw);
     35 	ltkd_cmdarg_parseinfo cmd[] = {
     36 		{.type = CMDARG_WIDGET, .widget_type = LTK_WIDGET_UNKNOWN, .optional = 0},
     37 		{.type = CMDARG_INT, .min = 0, .max = grid->rows - 1, .optional = 0},
     38 		{.type = CMDARG_INT, .min = 0, .max = grid->columns - 1, .optional = 0},
     39 		{.type = CMDARG_INT, .min = 0, .max = grid->rows, .optional = 0},
     40 		{.type = CMDARG_INT, .min = 0, .max = grid->columns, .optional = 0},
     41 		{.type = CMDARG_STICKY, .optional = 1},
     42 	};
     43 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
     44 		return 1;
     45 	int row = cmd[1].val.i, col = cmd[2].val.i;
     46 	int rowspan = cmd[3].val.i, colspan = cmd[4].val.i;
     47 	if (row + rowspan > grid->rows) {
     48 		err->type = ERR_GRID_INVALID_POSITION;
     49 		err->arg = 1;
     50 	}
     51 	if (col + colspan > grid->columns) {
     52 		err->type = ERR_GRID_INVALID_POSITION;
     53 		err->arg = 2;
     54 	}
     55 	/* FIXME: better error reporting for invalid grid position */
     56 	/* FIXME: check if recalculation deals properly with rowspan/columnspan
     57 	   that goes over the edge of the grid */
     58 	if (ltk_grid_add(
     59 	    widget->ltkid, cmd[0].val.widget->ltkid,
     60 	    row, col, rowspan, colspan,
     61 	    cmd[5].initialized ? cmd[5].val.sticky : 0)) {
     62 		err->type = ERR_WIDGET_IN_CONTAINER;
     63 		err->arg = 0;
     64 		return 1;
     65 	}
     66 	return 0;
     67 }
     68 
     69 /* grid <grid id> remove <widget id> */
     70 static int
     71 ltkd_grid_cmd_ungrid(
     72     ltk_widget_id windowid,
     73     ltkd_widget *widget,
     74     ltkd_cmd_token *tokens,
     75     size_t num_tokens,
     76     ltkd_error *err) {
     77 	(void)windowid;
     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(widget->ltkid, cmd[0].val.widget->ltkid)) {
     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_widget_id windowid,
     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_widget_id grid = ltk_grid_create(windowid, cmd[3].val.i, cmd[4].val.i);
    111 	if (!ltkd_widget_create(grid, cmd[1].val.str, NULL, 0, err)) {
    112 		ltk_widget_id_destroy(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_widget_id windowid,
    125     ltkd_widget *widget,
    126     ltkd_cmd_token *tokens,
    127     size_t num_tokens,
    128     ltkd_error *err) {
    129 	(void)windowid;
    130 	ltk_widget *gridw = ltk_get_widget_from_id(widget->ltkid);
    131 	ltk_grid *grid = LTK_CAST_GRID(gridw);
    132 	ltkd_cmdarg_parseinfo cmd[] = {
    133 		{.type = CMDARG_INT, .min = 0, .max = grid->rows - 1, .optional = 0},
    134 		{.type = CMDARG_INT, .min = 0, .max = 64, .optional = 0},
    135 	};
    136 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
    137 		return 1;
    138 	ltk_grid_set_row_weight(widget->ltkid, cmd[0].val.i, cmd[1].val.i);
    139 
    140 	return 0;
    141 }
    142 
    143 
    144 /* FIXME: 64 is completely arbitrary */
    145 /* FIXME: check for overflows in various grid calculations (at least when larger values are allowed) */
    146 /* grid <grid id> set-column-weight <column> <weight> */
    147 static int
    148 ltkd_grid_cmd_set_column_weight(
    149     ltk_widget_id windowid,
    150     ltkd_widget *widget,
    151     ltkd_cmd_token *tokens,
    152     size_t num_tokens,
    153     ltkd_error *err) {
    154 	(void)windowid;
    155 	ltk_widget *gridw = ltk_get_widget_from_id(widget->ltkid);
    156 	ltk_grid *grid = LTK_CAST_GRID(gridw);
    157 	ltkd_cmdarg_parseinfo cmd[] = {
    158 		{.type = CMDARG_INT, .min = 0, .max = grid->columns - 1, .optional = 0},
    159 		{.type = CMDARG_INT, .min = 0, .max = 64, .optional = 0},
    160 	};
    161 	if (ltkd_parse_cmd(tokens, num_tokens, cmd, LENGTH(cmd), err))
    162 		return 1;
    163 	ltk_grid_set_column_weight(widget->ltkid, cmd[0].val.i, cmd[1].val.i);
    164 
    165 	return 0;
    166 }
    167 
    168 static ltkd_cmd_info grid_cmds[] = {
    169 	{"add", &ltkd_grid_cmd_add, 0},
    170 	{"create", &ltkd_grid_cmd_create, 1},
    171 	{"remove", &ltkd_grid_cmd_ungrid, 0},
    172 	{"set-column-weight", &ltkd_grid_cmd_set_column_weight, 0},
    173 	{"set-row-weight", &ltkd_grid_cmd_set_row_weight, 0},
    174 };
    175 
    176 GEN_CMD_HELPERS(ltkd_grid_cmd, LTK_WIDGET_GRID, grid_cmds)