1 /*
2 * STFL - The Structured Terminal Forms Language/Library
3 * Copyright (C) 2006, 2007 Clifford Wolf <clifford@clifford.at>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301 USA
19 *
20 * wt_box.c: Widget types 'hbox' and 'vbox'
21 */
22
23 #include "stfl_internals.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 struct box_data {
29 char type;
30 };
31
wt_vbox_init(struct stfl_widget * w)32 static void wt_vbox_init(struct stfl_widget *w)
33 {
34 struct box_data *d = calloc(1, sizeof(struct box_data));
35 d->type = 'V';
36 w->internal_data = d;
37 }
38
wt_hbox_init(struct stfl_widget * w)39 static void wt_hbox_init(struct stfl_widget *w)
40 {
41 struct box_data *d = calloc(1, sizeof(struct box_data));
42 d->type = 'H';
43 w->internal_data = d;
44 }
45
wt_box_done(struct stfl_widget * w)46 static void wt_box_done(struct stfl_widget *w)
47 {
48 free(w->internal_data);
49 }
50
wt_box_prepare(struct stfl_widget * w,struct stfl_form * f)51 static void wt_box_prepare(struct stfl_widget *w, struct stfl_form *f)
52 {
53 struct box_data *d = w->internal_data;
54
55 w->min_w = 0;
56 w->min_h = 0;
57
58 struct stfl_widget *c = w->first_child;
59 while (c) {
60 if (stfl_widget_getkv_int(c, L".display", 1)) {
61 c->type->f_prepare(c, f);
62 if (d->type == 'H') {
63 if (w->min_h < c->min_h)
64 w->min_h = c->min_h;
65 w->min_w += c->min_w;
66 } else {
67 if (w->min_w < c->min_w)
68 w->min_w = c->min_w;
69 w->min_h += c->min_h;
70 }
71 }
72 c = c->next_sibling;
73 }
74 }
75
wt_box_draw(struct stfl_widget * w,struct stfl_form * f,WINDOW * win)76 static void wt_box_draw(struct stfl_widget *w, struct stfl_form *f, WINDOW *win)
77 {
78 struct box_data *d = w->internal_data;
79
80 int num_dyn_children = 0;
81 int min_w = 0, min_h = 0;
82 int i, j;
83
84 struct stfl_widget *c = w->first_child;
85 while (c)
86 {
87 if (stfl_widget_getkv_int(c, L".display", 1))
88 {
89 int size_w = stfl_widget_getkv_int(c, L".width", 0);
90 if (size_w < c->min_w) size_w = c->min_w;
91
92 int size_h = stfl_widget_getkv_int(c, L".height", 0);
93 if (size_h < c->min_h) size_h = c->min_h;
94
95 if (wcschr(stfl_widget_getkv_str(c, L".expand", L"vh"),
96 d->type == 'H' ? 'h' : 'v'))
97 num_dyn_children++;
98
99 if (d->type == 'H') {
100 min_w += size_w;
101 if (min_h < size_h)
102 min_h = size_h;
103 } else {
104 min_h += size_h;
105 if (min_w < size_w)
106 min_w = size_w;
107 }
108 }
109 c = c->next_sibling;
110 }
111
112 int box_x = w->x, box_y = w->y;
113 int box_w = w->w, box_h = w->h;
114
115 stfl_widget_style(w, f, win);
116 for (i=box_x; i<box_x+box_w; i++)
117 for (j=box_y; j<box_y+box_h; j++)
118 mvwaddch(win, j, i, ' ');
119
120 const wchar_t *tie = stfl_widget_getkv_str(w, L"tie", L"lrtb");
121
122 if (!wcschr(tie, L'l') && !wcschr(tie, L'r')) box_x += (box_w-min_w)/2;
123 if (!wcschr(tie, L'l') && wcschr(tie, L'r')) box_x += box_w-min_w;
124 if (!wcschr(tie, L'l') || !wcschr(tie, L'r')) box_w = min_w;
125
126 if (!wcschr(tie, L't') && !wcschr(tie, L'b')) box_y += (box_h-min_h)/2;
127 if (!wcschr(tie, L't') && wcschr(tie, L'b')) box_y += box_h-min_h;
128 if (!wcschr(tie, L't') || !wcschr(tie, L'b')) box_h = min_h;
129
130 int sizes_extra = (d->type == 'H' ? box_w - min_w : box_h - min_h);
131 int cursor = (d->type == 'H' ? box_x : box_y);
132
133 c = w->first_child;
134 for (i=0; c; i++)
135 {
136 if (stfl_widget_getkv_int(c, L".display", 1))
137 {
138 int size = stfl_widget_getkv_int(c,
139 d->type == 'H' ? L".width" : L".height", 0);
140
141 if (size < (d->type == 'H' ? c->min_w : c->min_h))
142 size = d->type == 'H' ? c->min_w : c->min_h;
143
144 if (wcschr(stfl_widget_getkv_str(c, L".expand", L"vh"),
145 d->type == 'H' ? 'h' : 'v')) {
146 int extra = sizes_extra / num_dyn_children--;
147 sizes_extra -= extra;
148 size += extra;
149 }
150
151 if (d->type == 'H') {
152 c->y = box_y;
153 c->x = cursor;
154 c->h = box_h;
155 c->w = size;
156 cursor += c->w;
157 } else {
158 c->x = box_x;
159 c->y = cursor;
160 c->w = box_w;
161 c->h = size;
162 cursor += c->h;
163 }
164
165 tie = stfl_widget_getkv_str(c, L".tie", L"lrtb");
166
167 if (!wcschr(tie, L'l') && !wcschr(tie, L'r')) c->x += (c->w - c->min_w)/2;
168 if (!wcschr(tie, L'l') && wcschr(tie, L'r')) c->x += c->w - c->min_w;
169 if (!wcschr(tie, L'l') || !wcschr(tie, L'r')) c->w = c->min_w;
170
171 if (!wcschr(tie, L't') && !wcschr(tie, L'b')) c->y += (c->h - c->min_h)/2;
172 if (!wcschr(tie, L't') && wcschr(tie, L'b')) c->y += c->h - c->min_h;
173 if (!wcschr(tie, L't') || !wcschr(tie, L'b')) c->h = c->min_h;
174
175 c->type->f_draw(c, f, win);
176 }
177 c = c->next_sibling;
178 }
179 }
180
wt_box_process(struct stfl_widget * w,struct stfl_widget * fw,struct stfl_form * f,wchar_t ch,int isfunckey)181 static int wt_box_process(struct stfl_widget *w, struct stfl_widget *fw, struct stfl_form *f, wchar_t ch, int isfunckey)
182 {
183 struct box_data *d = w->internal_data;
184
185 if (d->type == 'H')
186 {
187 if (stfl_matchbind(w, ch, isfunckey, L"left", L"LEFT"))
188 return stfl_focus_prev(w, fw, f);
189 if (stfl_matchbind(w, ch, isfunckey, L"right", L"RIGHT"))
190 return stfl_focus_next(w, fw, f);
191 }
192
193 if (d->type == 'V')
194 {
195 if (stfl_matchbind(w, ch, isfunckey, L"up", L"UP"))
196 return stfl_focus_prev(w, fw, f);
197 if (stfl_matchbind(w, ch, isfunckey, L"down", L"DOWN"))
198 return stfl_focus_next(w, fw, f);
199 }
200
201 return 0;
202 }
203
204 struct stfl_widget_type stfl_widget_type_vbox = {
205 L"vbox",
206 wt_vbox_init,
207 wt_box_done,
208 0, // f_enter
209 0, // f_leave
210 wt_box_prepare,
211 wt_box_draw,
212 wt_box_process
213 };
214
215 struct stfl_widget_type stfl_widget_type_hbox = {
216 L"hbox",
217 wt_hbox_init,
218 wt_box_done,
219 0, // f_enter
220 0, // f_leave
221 wt_box_prepare,
222 wt_box_draw,
223 wt_box_process
224 };
225
226