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