00001
00038 #include <stdint.h>
00039 #include <stdlib.h>
00040 #include <assert.h>
00041 #include <membag.h>
00042 #include <string.h>
00043 #include <util.h>
00044 #include <gfx/wtk.h>
00045
00054 enum wtk_check_box_state {
00056 WTK_CHECKBOX_NORMAL,
00058 WTK_CHECKBOX_PRESSED,
00059 };
00060
00068 struct wtk_check_box {
00070 struct win_window *container;
00072 char *caption;
00074 bool selected;
00076 enum wtk_check_box_state state;
00078 win_command_t command;
00079 };
00080
00089 struct win_window *wtk_check_box_as_child(struct wtk_check_box *check_box)
00090 {
00091 assert(check_box);
00092 return check_box->container;
00093 }
00094
00102 void wtk_check_box_toggle(struct wtk_check_box *check_box)
00103 {
00104 assert(check_box);
00105 check_box->selected = !check_box->selected;
00106 win_redraw(check_box->container);
00107 }
00108
00118 void wtk_check_box_set(struct wtk_check_box *check_box, bool selected)
00119 {
00120 assert(check_box);
00121 check_box->selected = selected;
00122 win_redraw(check_box->container);
00123 }
00124
00130 bool wtk_check_box_is_selected(struct wtk_check_box const *check_box)
00131 {
00132 assert(check_box);
00133 return check_box->selected;
00134 }
00135
00146 static bool wtk_check_box_handler(struct win_window *win,
00147 enum win_event_type type, void const *data)
00148 {
00149 struct win_command_event command;
00150
00151
00152 struct wtk_check_box *check_box =
00153 (struct wtk_check_box *)win_get_custom_data(win);
00154
00155 switch (type) {
00156 case WIN_EVENT_DRAW:
00157 {
00158
00159 assert(win == check_box->container);
00160
00161
00162
00163
00164 struct win_clip_region const *clip =
00165 (struct win_clip_region const *)data;
00166
00167
00168 gfx_draw_rect(clip->origin.x + WTK_CHECKBOX_BOX_X,
00169 clip->origin.y + WTK_CHECKBOX_BOX_Y,
00170 WTK_CHECKBOX_BOX_SIZE,
00171 WTK_CHECKBOX_BOX_SIZE,
00172 WTK_CHECKBOX_BOX_COLOR);
00173
00174
00175 if (check_box->selected) {
00176 gfx_draw_filled_rect(clip->origin.x +
00177 WTK_CHECKBOX_BOX_X + 2,
00178 clip->origin.y +
00179 WTK_CHECKBOX_BOX_Y + 2,
00180 WTK_CHECKBOX_BOX_SIZE - 4,
00181 WTK_CHECKBOX_BOX_SIZE - 4,
00182 WTK_CHECKBOX_SELECT_COLOR);
00183 }
00184
00185
00186 gfx_draw_string(check_box->caption,
00187 clip->origin.x + WTK_CHECKBOX_CAPTION_X,
00188 clip->origin.y + WTK_CHECKBOX_CAPTION_Y,
00189 &sysfont,
00190 WTK_CHECKBOX_CAPTION_COLOR,
00191 GFX_COLOR_TRANSPARENT);
00192
00193
00194
00195
00196 return true;
00197 }
00198
00199 case WIN_EVENT_POINTER:
00200 {
00201
00202 assert(win == check_box->container);
00203
00204
00205
00206
00207 struct win_pointer_event const *event =
00208 (struct win_pointer_event const *)data;
00209
00210 switch (event->type) {
00211 case WIN_POINTER_PRESS:
00212
00213
00214
00215
00216
00217
00218 if (check_box->state == WTK_CHECKBOX_NORMAL) {
00219 win_grab_pointer(check_box->container);
00220 check_box->state = WTK_CHECKBOX_PRESSED;
00221 win_redraw(check_box->container);
00222 }
00223 break;
00224
00225 case WIN_POINTER_RELEASE:
00226
00227
00228
00229 if (check_box->state == WTK_CHECKBOX_PRESSED) {
00230 bool is_inside;
00231
00232
00233 win_grab_pointer(NULL);
00234 check_box->state = WTK_CHECKBOX_NORMAL;
00235 win_redraw(check_box->container);
00236
00237
00238 is_inside = win_is_inside_window
00239 (check_box->container,
00240 &(event->pos));
00241
00242
00243 if (is_inside) {
00244 wtk_check_box_toggle(check_box);
00245
00246
00247 if (check_box->command) {
00248 command.sender =
00249 check_box->container;
00250 command.recipient =
00251 check_box->container;
00252 command.data =
00253 check_box->command;
00254 win_queue_command_event
00255 (&command);
00256 }
00257 }
00258 }
00259 break;
00260
00261 default:
00262 break;
00263 }
00264
00265
00266
00267
00268 return true;
00269 }
00270
00271 case WIN_EVENT_DESTROY:
00272
00273 assert(win == check_box->container);
00274
00275
00276
00277
00278 membag_free(check_box->caption);
00279 membag_free(check_box);
00280
00281
00282
00283
00284 return true;
00285
00286 default:
00287
00288 return false;
00289 }
00290 }
00291
00292
00302 void wtk_check_box_size_hint(struct win_point *size, const char *caption)
00303 {
00304 assert(size);
00305 assert(caption);
00306
00307 gfx_get_string_bounding_box(caption, &sysfont, &size->x, &size->y);
00308 size->x += WTK_CHECKBOX_CAPTION_X;
00309 size->y += max_s(WTK_CHECKBOX_CAPTION_Y + sysfont.height * sysfont.scale,
00310 WTK_CHECKBOX_BOX_SIZE);
00311 }
00312
00333 struct wtk_check_box *wtk_check_box_create(struct win_window *parent,
00334 struct win_area const *area,
00335 char const *caption, bool selected, win_command_t command)
00336 {
00337 struct win_attributes attr;
00338 struct wtk_check_box *check_box;
00339
00340 assert(area);
00341 assert(caption);
00342 assert(parent);
00343
00344
00345 check_box = membag_alloc(sizeof(struct wtk_check_box));
00346 if (!check_box) {
00347 goto outofmem_check_box;
00348 }
00349
00350 check_box->state = WTK_CHECKBOX_NORMAL;
00351 check_box->selected = selected;
00352 check_box->command = command;
00353
00354
00355 check_box->caption = membag_alloc((strlen(caption) + 1) * sizeof(char));
00356 if (!check_box->caption) {
00357 goto outofmem_caption;
00358 }
00359
00360 wtk_copy_string(check_box->caption, caption);
00361
00362
00363 attr.event_handler = wtk_check_box_handler;
00364 attr.custom = check_box;
00365
00366
00367 attr.area = *area;
00368 attr.background = NULL;
00369 attr.behavior = WIN_BEHAVIOR_REDRAW_PARENT;
00370
00371 check_box->container = win_create(parent, &attr);
00372 if (!check_box->container) {
00373 goto outofmem_container;
00374 }
00375
00376 return check_box;
00377
00378 outofmem_container:
00379 membag_free(check_box->caption);
00380
00381 outofmem_caption:
00382 membag_free(check_box);
00383
00384 outofmem_check_box:
00385 return NULL;
00386 }
00387