00001
00038 #include <stdint.h>
00039 #include <stdlib.h>
00040 #include <assert.h>
00041 #include <membag.h>
00042 #include <string.h>
00043 #include <gfx/wtk.h>
00044
00053 enum wtk_button_state {
00055 WTK_BUTTON_NORMAL,
00057 WTK_BUTTON_PRESSED,
00058 };
00059
00068 struct wtk_button {
00070 struct win_window *container;
00072 char *caption;
00074 win_command_t command_data;
00076 enum wtk_button_state state;
00077 };
00078
00087 struct win_window *wtk_button_as_child(struct wtk_button *button)
00088 {
00089 assert(button);
00090 return button->container;
00091 }
00092
00103 static bool wtk_button_handler(struct win_window *win,
00104 enum win_event_type type, void const *data)
00105 {
00106
00107 struct wtk_button *button =
00108 (struct wtk_button *)win_get_custom_data(win);
00109
00110 switch (type) {
00111 case WIN_EVENT_DRAW:
00112 {
00113
00114
00115 struct win_clip_region const *clip =
00116 (struct win_clip_region const *)data;
00117 struct win_area const *area = win_get_area(win);
00118
00119
00120
00121 gfx_color_t background_color;
00122 gfx_color_t caption_color;
00123
00124
00125 assert(win == button->container);
00126
00127 switch (button->state) {
00128 case WTK_BUTTON_NORMAL:
00129 background_color = WTK_BUTTON_BACKGROUND_COLOR;
00130 caption_color = WTK_BUTTON_CAPTION_COLOR;
00131 break;
00132
00133 case WTK_BUTTON_PRESSED:
00134 background_color = WTK_BUTTON_CAPTION_COLOR;
00135 caption_color = WTK_BUTTON_BACKGROUND_COLOR;
00136 break;
00137
00138 default:
00139 assert(false);
00140 background_color = WTK_BUTTON_BACKGROUND_COLOR;
00141 caption_color = WTK_BUTTON_CAPTION_COLOR;
00142 }
00143
00144
00145 gfx_draw_filled_rect(clip->origin.x, clip->origin.y,
00146 area->size.x, area->size.y,
00147 background_color);
00148
00149
00150 gfx_draw_rect(clip->origin.x, clip->origin.y,
00151 area->size.x, area->size.y,
00152 WTK_BUTTON_BORDER_COLOR);
00153
00154
00155
00156
00157 gfx_coord_t width;
00158 gfx_coord_t height;
00159
00160 gfx_get_string_bounding_box(button->caption, &sysfont,
00161 &width, &height);
00162
00163 gfx_draw_string(button->caption,
00164 clip->origin.x + (area->size.x / 2) -
00165 (width / 2),
00166 clip->origin.y + (area->size.y / 2) -
00167 (height / 2), &sysfont, caption_color,
00168 GFX_COLOR_TRANSPARENT);
00169
00170
00171
00172
00173 return true;
00174 }
00175
00176 case WIN_EVENT_POINTER:
00177 {
00178
00179 assert(win == button->container);
00180
00181
00182
00183
00184 struct win_pointer_event const *event =
00185 (struct win_pointer_event const *)data;
00186
00187 switch (event->type) {
00188 case WIN_POINTER_PRESS:
00189
00190
00191
00192
00193
00194
00195 if (button->state == WTK_BUTTON_NORMAL) {
00196 win_grab_pointer(button->container);
00197 button->state = WTK_BUTTON_PRESSED;
00198 win_redraw(button->container);
00199 }
00200 break;
00201
00202 case WIN_POINTER_RELEASE:
00203
00204
00205
00206 if (button->state == WTK_BUTTON_PRESSED) {
00207
00208 win_grab_pointer(NULL);
00209 button->state = WTK_BUTTON_NORMAL;
00210 win_redraw(button->container);
00211
00212
00213 bool isInside = win_is_inside_window
00214 (button->container,
00215 &(event->pos));
00216
00217
00218 if (isInside) {
00219 struct win_command_event
00220 command;
00221 command.sender = button->
00222 container;
00223 command.recipient =
00224 button->
00225 container;
00226 command.data = button->
00227 command_data;
00228 win_queue_command_event
00229 (&command);
00230 }
00231 }
00232 break;
00233
00234 default:
00235 break;
00236 }
00237
00238
00239
00240
00241 return true;
00242 }
00243
00244 case WIN_EVENT_DESTROY:
00245 {
00246
00247 assert(win == button->container);
00248
00249
00250
00251
00252
00253 membag_free(button->caption);
00254 membag_free(button);
00255
00256
00257
00258
00259 return true;
00260 }
00261
00262 default:
00263
00264 return false;
00265 }
00266 }
00267
00277 void wtk_button_size_hint(struct win_point *size, const char *caption)
00278 {
00279 assert(size);
00280 assert(caption);
00281
00282 gfx_get_string_bounding_box(caption, &sysfont, &size->x, &size->y);
00283
00284 size->x += 2;
00285 size->y += 2;
00286 }
00287
00288
00307 struct wtk_button *wtk_button_create(struct win_window *parent,
00308 struct win_area const *area,
00309 char const *caption, win_command_t command_data)
00310 {
00311 struct win_attributes attr;
00312 struct wtk_button *button;
00313
00314 assert(area);
00315 assert(caption);
00316 assert(parent);
00317 assert(command_data);
00318
00319
00320 button = membag_alloc(sizeof(struct wtk_button));
00321 if (!button) {
00322 goto outofmem_button;
00323 }
00324
00325 button->state = WTK_BUTTON_NORMAL;
00326 button->command_data = command_data;
00327
00328
00329 button->caption = membag_alloc((strlen(caption) + 1) * sizeof(char));
00330 if (!button->caption) {
00331 goto outofmem_caption;
00332 }
00333
00334 wtk_copy_string(button->caption, caption);
00335
00336
00337 attr.event_handler = wtk_button_handler;
00338 attr.custom = button;
00339
00340
00341 attr.area = *area;
00342 attr.background = NULL;
00343 attr.behavior = 0x00;
00344
00345 button->container = win_create(parent, &attr);
00346 if (!button->container) {
00347 goto outofmem_container;
00348 }
00349
00350 return button;
00351
00352 outofmem_container:
00353 membag_free(button->caption);
00354
00355 outofmem_caption:
00356 membag_free(button);
00357
00358 outofmem_button:
00359 return NULL;
00360 }
00361