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", <kd_grid_cmd_add, 0}, 168 {"create", <kd_grid_cmd_create, 1}, 169 {"remove", <kd_grid_cmd_ungrid, 0}, 170 {"set-column-weight", <kd_grid_cmd_set_column_weight, 0}, 171 {"set-row-weight", <kd_grid_cmd_set_row_weight, 0}, 172 }; 173 174 GEN_CMD_HELPERS(ltkd_grid_cmd, LTK_WIDGET_GRID, grid_cmds)