initial commit
[windtk] / src / widget.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include "wtimpl.h"
4
5 wt_widget *wt_alloc_widget(wt_widget *par)
6 {
7         wt_widget *w;
8         if(!(w = wt_zalloc(sizeof *w))) {
9                 return 0;
10         }
11         w->type = WT_TYPE_WIDGET;
12
13         if(par) {
14                 wt_add_child(par, w);
15         }
16         return w;
17 }
18
19 void wt_free_widget(wt_widget *w)
20 {
21         if(w) {
22                 wt_free(w->text);
23                 wt_free(w->child);
24                 wt_free(w);
25         }
26 }
27
28 void wt_free_tree(wt_widget *tree)
29 {
30         int i;
31
32         if(!tree) return;
33
34         for(i=0; i<tree->num_child; i++) {
35                 wt_free_tree(tree->child[i]);
36         }
37         wt_free_widget(tree);
38 }
39
40 int wt_type(wt_widget *w)
41 {
42         return w->type;
43 }
44
45 int wt_set_text(wt_widget *w, const char *text)
46 {
47         char *s;
48
49         if(!(s = wt_alloc(strlen(text) + 1))) {
50                 return -1;
51         }
52         strcpy(s, text);
53         wt_free(w->text);
54         w->text = s;
55         return 0;
56 }
57
58 const char *wt_text(wt_widget *w)
59 {
60         return w->text;
61 }
62
63 static int find_child(wt_widget *w, wt_widget *c)
64 {
65         int i;
66         for(i=0; i<w->num_child; i++) {
67                 if(w->child[i] == c) {
68                         return i;
69                 }
70         }
71         return -1;
72 }
73
74 int wt_add_child(wt_widget *w, wt_widget *c)
75 {
76         if(find_child(w, c) != -1) {
77                 return 0;
78         }
79         if(c->parent) {
80                 wt_remove_child(c->parent, c);
81         }
82
83         if(w->num_child >= w->max_child) {
84                 void *newarr;
85                 int newsz = w->max_child ? w->max_child << 1 : 8;
86                 if(!(newarr = wt_alloc(newsz * sizeof *w->child))) {
87                         return -1;
88                 }
89                 memcpy(newarr, w->child, w->num_child * sizeof *w->child);
90                 wt_free(w->child);
91                 w->child = newarr;
92                 w->max_child = newsz;
93         }
94
95         w->child[w->num_child++] = c;
96         return 0;
97 }
98
99 int wt_remove_child(wt_widget *w, wt_widget *c)
100 {
101         int idx;
102
103         if(!w->num_child || (idx = find_child(w, c)) == -1) {
104                 return -1;
105         }
106         w->child[idx] = w->child[--w->num_child];
107
108         if(w->max_child > 8 && w->num_child < w->max_child / 3) {
109                 void *newarr;
110                 int newsz = w->max_child >> 1;
111                 if(!(newarr = wt_alloc(newsz * sizeof *w->child))) {
112                         return -1;
113                 }
114                 memcpy(newarr, w->child, w->num_child * sizeof *w->child);
115                 wt_free(w->child);
116                 w->child = newarr;
117                 w->max_child = newsz;
118         }
119         return 0;
120 }
121
122 wt_widget *wt_parent(wt_widget *w)
123 {
124         return w->parent;
125 }
126
127 wt_widget *wt_widget_window(wt_widget *w)
128 {
129         wt_widget *par = w;
130         while(par && par->type != WT_TYPE_WINDOW) {
131                 par = par->parent;
132         }
133         return par;
134 }
135
136 int wt_child_count(wt_widget *w)
137 {
138         return w->num_child;
139 }
140
141 wt_widget *wt_child(wt_widget *w, int idx)
142 {
143         if(idx < 0 || idx >= w->num_child) {
144                 return 0;
145         }
146         return w->child[idx];
147 }
148
149 void wt_move(wt_widget *w, int x, int y)
150 {
151         w->rect.x = x;
152         w->rect.y = y;
153         /* TODO: invalidate something */
154 }
155
156 void wt_resize(wt_widget *w, int x, int y)
157 {
158         w->rect.width = x;
159         w->rect.height = y;
160         /* TODO: invalidate something */
161 }
162
163 int *wt_position(wt_widget *w, int *xret, int *yret)
164 {
165         if(xret) *xret = w->rect.x;
166         if(yret) *yret = w->rect.y;
167         return &w->rect.x;
168 }
169
170 int *wt_size(wt_widget *w, int *xret, int *yret)
171 {
172         if(xret) *xret = w->rect.width;
173         if(yret) *yret = w->rect.height;
174         return &w->rect.width;
175 }
176
177 int wt_hittest(wt_widget *w, int x, int y)
178 {
179         return x >= w->rect.x && y >= w->rect.y && x < w->rect.x + w->rect.width &&
180                 y < w->rect.y + w->rect.height;
181 }
182
183 wt_widget *wt_widget_at(int x, int y)
184 {
185         int i;
186         wt_widget *w, *c;
187
188         if(!wt_hittest(wt->root, x, y)) {
189                 return 0;
190         }
191
192         w = 0;
193         c = wt->root;
194         do {
195                 w = c;
196                 c = 0;
197                 for(i=0; i<w->num_child; i++) {
198                         if(wt_hittest(w->child[i], x, y)) {
199                                 c = w->child[i];
200                                 break;
201                         }
202                 }
203         } while(c);
204
205         return w;
206 }
207
208 /*
209 void wt_layout(wt_widget *w, int layout);
210 void wt_padding(wt_widget *w, int pad);
211 void wt_relayout(wt_widget *w);
212
213 void wt_focus(wt_widget *w);
214 void wt_unfocus(wt_widget *w);
215 int wt_isfocused(wt_widget *w);
216
217 void wt_hover(wt_widget *w);
218 void wt_unhover(wt_widget *w);
219 int wt_ishover(wt_widget *w);
220
221 void wt_enable(wt_widget *w);
222 void wt_disable(wt_widget *w);
223 int wt_isenabled(wt_widget *w);
224 */
225
226 void wt_callback(wt_widget *w, int type, wt_callback_func func, void *cls)
227 {
228         w->cb[type] = func;
229         w->cbcls[type] = cls;
230 }