2 * Routines to insert and delete rows in a GtkTable.
3 * The table is assumed to have no children that span more than one
4 * row: odd displays may result if this is not true.
6 * Rows are numbered by the value of the top_attach field;
7 * a table with 2 rows has rows numbered 0 and 1, etc.
13 static GtkTableChild
*
14 collect_children(GtkTable
*table
, int row
, int *nchp
)
16 GtkTableChild
*row_children
;
17 GtkTableChild
*table_child
;
22 row_children
= g_new0(GtkTableChild
, table
->ncols
);
25 /* locate all of the relevant children, and add an extra reference
27 for (list
= table
->children
; list
; list
= list
->next
) {
28 table_child
= list
->data
;
30 if(table_child
->top_attach
== row
) {
31 if(nch
== table
->ncols
) {
32 g_error("collect_children: too many children on row %d\n", row
);
35 row_children
[nch
++] = *table_child
;
36 gtk_widget_ref(table_child
->widget
);
45 reattach_children(GtkTable
*table
, GtkTableChild
*row_children
, int nch
,
49 GtkAttachOptions xoptions
;
50 GtkAttachOptions yoptions
;
52 /* add in new position and unref */
53 for(i
= 0; i
< nch
; i
++) {
54 xoptions
= row_children
[i
].xexpand
55 | row_children
[i
].xshrink
<<1
56 | row_children
[i
].xfill
<<2;
57 yoptions
= row_children
[i
].yexpand
58 | row_children
[i
].yshrink
<<1
59 | row_children
[i
].yfill
<<2;
61 gtk_table_attach(table
, row_children
[i
].widget
,
62 row_children
[i
].left_attach
,
63 row_children
[i
].right_attach
,
65 row
+ (row_children
[i
].bottom_attach
-
66 row_children
[i
].top_attach
),
69 row_children
[i
].xpadding
,
70 row_children
[i
].ypadding
);
72 gtk_widget_unref(row_children
[i
].widget
);
79 * move a table row to another row position.
82 gtk_table_move_row(GtkTable
*table
, int from
, int to
)
84 GtkTableChild
*row_children
;
87 GtkTableChild
*table_child
;
88 GtkAttachOptions xoptions
;
89 GtkAttachOptions yoptions
;
92 /* printf("move row %d to %d: ", from, to); */
93 row_children
= g_new(GtkTableChild
, table
->ncols
);
96 /* locate all of the relevant children, and add an extra reference
98 for (list
= table
->children
; list
; list
= list
->next
) {
99 table_child
= list
->data
;
101 if(table_child
->top_attach
== from
) {
102 if(nch
== table
->ncols
) {
103 g_error("gtk_table_move_row: too many children on row %d\n", from
);
106 row_children
[nch
++] = *table_child
;
107 gtk_widget_ref(table_child
->widget
);
111 /* remove from old position */
112 for(i
= 0; i
< nch
; i
++) {
113 gtk_container_remove(GTK_CONTAINER(table
), row_children
[i
].widget
);
115 /* add in new position and unref */
116 for(i
= 0; i
< nch
; i
++) {
117 xoptions
= row_children
[i
].xexpand
118 | row_children
[i
].xshrink
<<1
119 | row_children
[i
].xfill
<<2;
120 yoptions
= row_children
[i
].yexpand
121 | row_children
[i
].yshrink
<<1
122 | row_children
[i
].yfill
<<2;
124 gtk_table_attach(table
, row_children
[i
].widget
,
125 row_children
[i
].left_attach
,
126 row_children
[i
].right_attach
,
128 to
+ (row_children
[i
].bottom_attach
-
129 row_children
[i
].top_attach
),
132 row_children
[i
].xpadding
,
133 row_children
[i
].ypadding
);
135 gtk_widget_unref(row_children
[i
].widget
);
137 /* printf("%d widgets moved\n", nch); */
139 g_free(row_children
);
143 * Insert a new empty row into a GtkTable just before the specified row,
144 * moving subsequent rows down.
145 * - resize the table one larger
146 * - move rows down to put the hole where it belongs
149 gtk_table_insert_row(GtkWidget
*widget
, int row
)
152 int old_nrows
, old_ncols
;
154 table
= GTK_TABLE(widget
);
155 old_nrows
= table
->nrows
;
156 old_ncols
= table
->ncols
;
158 gtk_table_resize(table
, old_nrows
+1, old_ncols
);
160 for(i
= old_nrows
; i
> row
; i
--) {
161 gtk_table_move_row(table
, i
-1, i
);
167 * Delete the indicated row of a GtkTable, moving subsequent rows up.
168 * - remove the specified row
170 * - resize the table one smaller
173 gtk_table_delete_row(GtkWidget
*widget
, int row
)
176 GtkTableChild
*table_child
;
178 GList
*del_list
= NULL
;
179 int old_nrows
, old_ncols
;
181 table
= GTK_TABLE(widget
);
182 old_nrows
= table
->nrows
;
183 old_ncols
= table
->ncols
;
185 /* remove widgets from the old row
186 can't delete while walking the list; must make a temporary list
188 for (list
= table
->children
; list
; list
= list
->next
) {
189 table_child
= list
->data
;
190 if(table_child
->top_attach
== row
) {
191 del_list
= g_list_append(del_list
, table_child
->widget
);
197 child
= del_list
->data
;
198 /* printf("remove child 0x%lx\n", child); */
199 gtk_container_remove(GTK_CONTAINER(table
), child
);
200 del_list
= g_list_remove(del_list
, child
);
203 for(i
= row
; i
< old_nrows
-1; i
++) {
204 gtk_table_move_row(table
, i
+1, i
);
207 gtk_table_resize(table
, old_nrows
-1, old_ncols
);
211 * Reorder a table, moving row FROM to position TO, and shifting
212 * all rows in between up or down one row.
213 * given this arrangement:
218 rotate_rows(, 2, 0) produces this result: ("up" case)
223 while applying rotate_rows(, 1, 3) to the original produces: ("down" case)
230 gtk_table_rotate_rows(GtkWidget
*widget
, int from
, int to
)
232 GtkTable
*table
= GTK_TABLE(widget
);
233 int down
; /* does the named "jumping" row move up or down? */
234 GtkTableChild
*moving_children
;
237 if(to
== from
) return;
238 else if(to
> from
) down
= 1;
241 /* collect the children in the row that's jumping */
242 moving_children
= collect_children(table
, from
, &nch
);
243 /* remove them from their old row */
244 for(i
= 0; i
< nch
; i
++) {
245 gtk_container_remove(GTK_CONTAINER(table
), moving_children
[i
].widget
);
248 /* now move the other ones one position.
249 * if the "jumping" row moves down, thers move up, etc. */
251 for(i
= from
; i
< to
; i
++) {
252 gtk_table_move_row(table
, i
+1, i
);
255 for(i
= from
; i
> to
; i
--) {
256 gtk_table_move_row(table
, i
-1, i
);
260 /* finally, put those children back down in the vacated target row */
261 reattach_children(table
, moving_children
, nch
, to
);
262 g_free(moving_children
);
267 * given a pointer to a child widget of a table,
268 * return the (top_attach) row number it is currently on.
271 gtk_table_get_child_row(GtkWidget
*widget
, GtkWidget
*child
)
274 GtkTableChild
*table_child
;
277 table
= GTK_TABLE(widget
);
279 for (list
= table
->children
; list
; list
= list
->next
) {
280 table_child
= list
->data
;
282 if(table_child
->widget
== child
)
283 return table_child
->top_attach
;