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
00061 struct wtk_progress_bar {
00063 struct win_window *container;
00065 uint8_t maximum;
00067 uint8_t value;
00069 uint8_t position;
00071 uint8_t option;
00073 gfx_color_t fill_color;
00075 gfx_color_t background_color;
00076 };
00077
00088 struct win_window *wtk_progress_bar_as_child(struct wtk_progress_bar *bar)
00089 {
00090 assert(bar);
00091 return bar->container;
00092 }
00093
00106 bool wtk_progress_bar_set_value(struct wtk_progress_bar *bar, uint8_t value)
00107 {
00108 uint8_t length;
00109 uint8_t option;
00110 uint8_t maximum;
00111 struct win_area const *area;
00112
00113 assert(bar);
00114 assert(value <= bar->maximum);
00115
00116 if (value != bar->value) {
00117 bar->value = value;
00118 option = bar->option;
00119 maximum = bar->maximum;
00120 area = win_get_area(bar->container);
00121
00122
00123 if (option & WTK_PROGRESS_BAR_VERTICAL) {
00124 length = area->size.y;
00125 } else {
00126 length = area->size.x;
00127 }
00128
00129 length -= 2;
00130
00131 if (option & WTK_PROGRESS_BAR_INVERT) {
00132 value = maximum - value;
00133 }
00134
00135 bar->position = wtk_rescale_value(value, maximum, length);
00136 win_redraw(bar->container);
00137
00138 return true;
00139
00140 } else {
00141 return false;
00142 }
00143 }
00144
00152 uint8_t wtk_progress_bar_get_value(struct wtk_progress_bar *bar)
00153 {
00154 assert(bar);
00155 return bar->value;
00156 }
00157
00168 void wtk_progress_bar_set_colors(struct wtk_progress_bar *bar,
00169 gfx_color_t fill_color, gfx_color_t background_color)
00170 {
00171 assert(bar);
00172
00173 if (bar->option & WTK_PROGRESS_BAR_INVERT) {
00174 bar->fill_color = background_color;
00175 bar->background_color = fill_color;
00176 } else {
00177 bar->fill_color = fill_color;
00178 bar->background_color = background_color;
00179 }
00180 }
00181
00195 static bool wtk_progress_bar_handler(struct win_window *win,
00196 enum win_event_type type, void const *data)
00197 {
00198 struct win_clip_region const *clip;
00199 struct win_area const *area;
00200 struct wtk_progress_bar *bar;
00201 uint8_t position;
00202 uint8_t option;
00203
00204 bar = (struct wtk_progress_bar *)win_get_custom_data(win);
00205
00206
00207 assert(win == bar->container);
00208
00209 switch (type) {
00210 case WIN_EVENT_DRAW:
00211
00212
00213
00214
00215 clip = (struct win_clip_region const *)data;
00216 area = win_get_area(win);
00217
00218 position = bar->position;
00219 option = bar->option;
00220
00221
00222 gfx_draw_rect(clip->origin.x, clip->origin.y, area->size.x,
00223 area->size.y, WTK_PROGRESS_BAR_BORDER_COLOR);
00224
00225
00226
00227
00228
00229
00230 if (option & WTK_PROGRESS_BAR_VERTICAL) {
00231
00232 gfx_draw_filled_rect(clip->origin.x + 1,
00233 clip->origin.y + 1,
00234 area->size.x - 2,
00235 position, bar->fill_color);
00236
00237 gfx_draw_filled_rect(clip->origin.x + 1,
00238 clip->origin.y + 1 + position,
00239 area->size.x - 2,
00240 area->size.y - 2 - position,
00241 bar->background_color);
00242 } else {
00243
00244 gfx_draw_filled_rect(clip->origin.x + 1,
00245 clip->origin.y + 1,
00246 bar->position,
00247 area->size.y - 2, bar->fill_color);
00248
00249 gfx_draw_filled_rect(clip->origin.x + 1 + position,
00250 clip->origin.y + 1,
00251 area->size.x - 2 - position,
00252 area->size.y - 2,
00253 bar->background_color);
00254 }
00255
00256
00257
00258
00259 return true;
00260
00261 case WIN_EVENT_DESTROY:
00262
00263
00264
00265 membag_free(bar);
00266 return true;
00267
00268 default:
00269 return false;
00270 }
00271 }
00272
00308 struct wtk_progress_bar *wtk_progress_bar_create(struct win_window *parent,
00309 struct win_area const *area, uint8_t maximum, uint8_t value,
00310 gfx_color_t fill_color, gfx_color_t background_color,
00311 uint8_t option)
00312 {
00313 uint8_t length;
00314
00315
00316 assert(maximum > 0);
00317 assert(value <= maximum);
00318 assert(area);
00319 assert(parent);
00320
00321
00322 struct win_attributes attr;
00323
00324
00325 struct wtk_progress_bar *bar =
00326 membag_alloc(sizeof(struct wtk_progress_bar));
00327 if (!bar) {
00328 goto outofmem_bar;
00329 }
00330
00331
00332 bar->maximum = maximum;
00333 bar->value = value;
00334 bar->option = option;
00335
00336
00337
00338
00339 if (option & WTK_PROGRESS_BAR_INVERT) {
00340 bar->fill_color = background_color;
00341 bar->background_color = fill_color;
00342 value = maximum - value;
00343 } else {
00344 bar->fill_color = fill_color;
00345 bar->background_color = background_color;
00346 }
00347
00348
00349 attr.event_handler = wtk_progress_bar_handler;
00350 attr.custom = bar;
00351
00352
00353
00354
00355 attr.area = *area;
00356 assert(attr.area.size.x > 3);
00357 assert(attr.area.size.y > 3);
00358
00359 if (option & WTK_PROGRESS_BAR_VERTICAL) {
00360 assert(attr.area.size.y < (uint8_t) ~ 0);
00361 length = attr.area.size.y;
00362 } else {
00363 assert(attr.area.size.x < (uint8_t) ~ 0);
00364 length = attr.area.size.x;
00365 }
00366
00367 length -= 2;
00368
00369
00370 bar->position = wtk_rescale_value(value, maximum, length);
00371
00372
00373
00374
00375 attr.background = NULL;
00376
00377
00378
00379
00380 attr.behavior = 0;
00381
00382
00383 bar->container = win_create(parent, &attr);
00384 if (!bar->container) {
00385 goto outofmem_container;
00386 }
00387
00388 return bar;
00389
00390 outofmem_container:
00391 membag_free(bar);
00392
00393 outofmem_bar:
00394 return NULL;
00395 }
00396