widget.c 20.2 KB
Newer Older
B
bernard.xiong 已提交
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * File      : widget.c
 * This file is part of RTGUI in RT-Thread RTOS
 * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2009-10-04     Bernard      first version
13
 * 2010-06-26     Bernard      add user_data to widget structure
B
bernard.xiong 已提交
14
 */
15

B
bernard.xiong 已提交
16
#include <rtgui/dc_client.h>
17
#include <rtgui/rtgui_app.h>
B
bernard.xiong 已提交
18 19
#include <rtgui/widgets/widget.h>
#include <rtgui/widgets/window.h>
20 21
#include <rtgui/widgets/container.h>
#include <rtgui/widgets/notebook.h>
B
bernard.xiong 已提交
22 23 24

static void _rtgui_widget_constructor(rtgui_widget_t *widget)
{
25
    if (!widget) return;
B
bernard.xiong 已提交
26

27 28
    /* set default flag */
    widget->flag = RTGUI_WIDGET_FLAG_DEFAULT;
B
bernard.xiong 已提交
29

30 31
    /* init list */
    rtgui_list_init(&(widget->sibling));
B
bernard.xiong 已提交
32

33 34 35 36 37 38 39
    /* init gc */
    widget->gc.foreground = default_foreground;
    widget->gc.background = default_background;
    widget->gc.font = rtgui_font_default();
    widget->gc.textstyle = RTGUI_TEXTSTYLE_NORMAL;
    widget->gc.textalign = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
    widget->align = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
B
bernard.xiong 已提交
40

41 42 43 44 45
    /* clear the garbage value of extent and clip */
    widget->extent.x1 = widget->extent.y1 = 0;
    widget->extent.x2 = widget->extent.y2 = 0;
    rtgui_region_init_with_extents(&widget->clip, &widget->extent);

46 47 48
    /* set parent and toplevel root */
    widget->parent        = RT_NULL;
    widget->toplevel      = RT_NULL;
B
bernard.xiong 已提交
49

50 51 52
    /* some common event handler */
    widget->on_focus_in   = RT_NULL;
    widget->on_focus_out  = RT_NULL;
53 54

#ifndef RTGUI_USING_SMALL_SIZE
55 56 57 58 59
    widget->on_draw       = RT_NULL;
    widget->on_mouseclick = RT_NULL;
    widget->on_key        = RT_NULL;
    widget->on_size       = RT_NULL;
    widget->on_command    = RT_NULL;
60
#endif
B
bernard.xiong 已提交
61

62 63
    /* set default event handler */
    rtgui_object_set_event_handler(RTGUI_OBJECT(widget), rtgui_widget_event_handler);
B
bernard.xiong 已提交
64

65 66
    /* init user data private to 0 */
    widget->user_data = 0;
67

68 69
    /* init clip information */
    rtgui_region_init(&(widget->clip));
70

71 72
    /* init hardware dc */
    rtgui_dc_client_init(widget);
B
bernard.xiong 已提交
73 74 75 76 77
}

/* Destroys the widget */
static void _rtgui_widget_destructor(rtgui_widget_t *widget)
{
78
    if (widget == RT_NULL) return;
B
bernard.xiong 已提交
79

80 81 82 83
    if (widget->parent != RT_NULL && RTGUI_IS_CONTAINER(widget->parent))
    {
        /* remove widget from parent's children list */
        rtgui_list_remove(&(RTGUI_CONTAINER(widget->parent)->children), &(widget->sibling));
B
bernard.xiong 已提交
84

85 86
        widget->parent = RT_NULL;
    }
B
bernard.xiong 已提交
87

88 89
    /* fini clip region */
    rtgui_region_fini(&(widget->clip));
B
bernard.xiong 已提交
90 91
}

92
DEFINE_CLASS_TYPE(widget, "widget",
93 94 95 96
                  RTGUI_OBJECT_TYPE,
                  _rtgui_widget_constructor,
                  _rtgui_widget_destructor,
                  sizeof(struct rtgui_widget));
97
RTM_EXPORT(_rtgui_widget);
B
bernard.xiong 已提交
98 99 100

rtgui_widget_t *rtgui_widget_create(rtgui_type_t *widget_type)
{
101
    struct rtgui_widget *widget;
B
bernard.xiong 已提交
102

103
    widget = RTGUI_WIDGET(rtgui_object_create(widget_type));
B
bernard.xiong 已提交
104

105
    return widget;
B
bernard.xiong 已提交
106
}
107
RTM_EXPORT(rtgui_widget_create);
B
bernard.xiong 已提交
108

109
void rtgui_widget_destroy(rtgui_widget_t *widget)
B
bernard.xiong 已提交
110
{
111
    rtgui_object_destroy(RTGUI_OBJECT(widget));
B
bernard.xiong 已提交
112
}
113
RTM_EXPORT(rtgui_widget_destroy);
B
bernard.xiong 已提交
114

115
void rtgui_widget_set_rect(rtgui_widget_t *widget, const rtgui_rect_t *rect)
B
bernard.xiong 已提交
116
{
117
    int delta_x, delta_y;
118

119
    if (widget == RT_NULL || rect == RT_NULL) return;
B
bernard.xiong 已提交
120

121 122 123 124 125
    /* move to a logic position if it's a container widget */
    if (RTGUI_IS_CONTAINER(widget))
    {
        delta_x = rect->x1 - widget->extent.x1;
        delta_y = rect->y1 - widget->extent.y1;
126

127 128
        rtgui_widget_move_to_logic(widget, delta_x, delta_y);
    }
129

130 131 132 133 134 135 136
    /* update extent rectangle */
    widget->extent = *rect;
    if (RTGUI_IS_CONTAINER(widget))
    {
        /* re-do layout */
        rtgui_container_layout(RTGUI_CONTAINER(widget));
    }
B
bernard.xiong 已提交
137

138 139 140
    /* reset mini width and height */
    widget->mini_width  = rtgui_rect_width(widget->extent);
    widget->mini_height = rtgui_rect_height(widget->extent);
B
bernard.xiong 已提交
141

142 143 144 145 146
    /* it's not empty, fini it */
    if (rtgui_region_not_empty(&(widget->clip)))
    {
        rtgui_region_fini(&(widget->clip));
    }
B
bernard.xiong 已提交
147

148 149 150 151 152 153 154
    /* reset clip info */
    rtgui_region_init_with_extents(&(widget->clip), rect);
    if ((widget->parent != RT_NULL) && (widget->toplevel != RT_NULL))
    {
        /* update widget clip */
        rtgui_widget_update_clip(widget->parent);
    }
B
bernard.xiong 已提交
155
}
156
RTM_EXPORT(rtgui_widget_set_rect);
B
bernard.xiong 已提交
157

158
void rtgui_widget_set_rectangle(rtgui_widget_t *widget, int x, int y, int width, int height)
159
{
160
    rtgui_rect_t rect;
161

162 163 164 165
    rect.x1 = x;
    rect.y1 = y;
    rect.x2 = x + width;
    rect.y2 = y + height;
166

167
    rtgui_widget_set_rect(widget, &rect);
168
}
169
RTM_EXPORT(rtgui_widget_set_rectangle);
170

171
void rtgui_widget_set_parent(rtgui_widget_t *widget, rtgui_widget_t *parent)
172
{
173 174
    /* set parent and toplevel widget */
    widget->parent = parent;
175
}
176
RTM_EXPORT(rtgui_widget_set_parent);
177

178
void rtgui_widget_get_extent(rtgui_widget_t *widget, rtgui_rect_t *rect)
179
{
180 181
    RT_ASSERT(widget != RT_NULL);
    RT_ASSERT(rect != RT_NULL);
182

183
    *rect = widget->extent;
184
}
185
RTM_EXPORT(rtgui_widget_get_extent);
186

187
void rtgui_widget_set_miniwidth(rtgui_widget_t *widget, int width)
B
bernard.xiong 已提交
188
{
189
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
190

191
    widget->mini_width = width;
B
bernard.xiong 已提交
192
}
193
RTM_EXPORT(rtgui_widget_set_miniwidth);
B
bernard.xiong 已提交
194

195
void rtgui_widget_set_miniheight(rtgui_widget_t *widget, int height)
B
bernard.xiong 已提交
196
{
197
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
198

199
    widget->mini_height = height;
B
bernard.xiong 已提交
200
}
201
RTM_EXPORT(rtgui_widget_set_miniheight);
B
bernard.xiong 已提交
202 203 204 205

/*
 * This function moves widget and its children to a logic point
 */
206
void rtgui_widget_move_to_logic(rtgui_widget_t *widget, int dx, int dy)
B
bernard.xiong 已提交
207
{
208 209
    struct rtgui_list_node *node;
    rtgui_widget_t *child;
B
bernard.xiong 已提交
210

211
    if (widget == RT_NULL) return;
B
bernard.xiong 已提交
212

213
    rtgui_rect_moveto(&(widget->extent), dx, dy);
B
bernard.xiong 已提交
214

215 216 217 218 219 220
    /* move each child */
    if (RTGUI_IS_CONTAINER(widget))
    {
        rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
        {
            child = rtgui_list_entry(node, rtgui_widget_t, sibling);
B
bernard.xiong 已提交
221

222 223 224
            rtgui_widget_move_to_logic(child, dx, dy);
        }
    }
B
bernard.xiong 已提交
225
}
226
RTM_EXPORT(rtgui_widget_move_to_logic);
B
bernard.xiong 已提交
227

228
void rtgui_widget_get_rect(rtgui_widget_t *widget, rtgui_rect_t *rect)
B
bernard.xiong 已提交
229
{
230
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
231

232 233 234 235 236 237
    if (rect != RT_NULL)
    {
        rect->x1 = rect->y1 = 0;
        rect->x2 = widget->extent.x2 - widget->extent.x1;
        rect->y2 = widget->extent.y2 - widget->extent.y1;
    }
B
bernard.xiong 已提交
238
}
239
RTM_EXPORT(rtgui_widget_get_rect);
B
bernard.xiong 已提交
240

241 242 243
/**
 * set widget draw style
 */
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
void rtgui_widget_set_border(rtgui_widget_t *widget, rt_uint32_t style)
{
    RT_ASSERT(widget != RT_NULL);

    widget->border_style = style;
    switch (style)
    {
    case RTGUI_BORDER_NONE:
        widget->border = 0;
        break;
    case RTGUI_BORDER_SIMPLE:
    case RTGUI_BORDER_UP:
    case RTGUI_BORDER_DOWN:
        widget->border = 1;
        break;
    case RTGUI_BORDER_STATIC:
    case RTGUI_BORDER_RAISE:
    case RTGUI_BORDER_SUNKEN:
    case RTGUI_BORDER_BOX:
    case RTGUI_BORDER_EXTRA:
        widget->border = 2;
        break;
    default:
        widget->border = 2;
        break;
    }
270
}
271
RTM_EXPORT(rtgui_widget_set_border);
272

273
void rtgui_widget_set_onfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
B
bernard.xiong 已提交
274
{
275
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
276

277
    widget->on_focus_in = handler;
B
bernard.xiong 已提交
278
}
279
RTM_EXPORT(rtgui_widget_set_onfocus);
B
bernard.xiong 已提交
280

281
void rtgui_widget_set_onunfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
B
bernard.xiong 已提交
282
{
283
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
284

285
    widget->on_focus_out = handler;
B
bernard.xiong 已提交
286
}
287
RTM_EXPORT(rtgui_widget_set_onunfocus);
B
bernard.xiong 已提交
288

289
#ifndef RTGUI_USING_SMALL_SIZE
290
void rtgui_widget_set_ondraw(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
B
bernard.xiong 已提交
291
{
292
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
293

294
    widget->on_draw = handler;
B
bernard.xiong 已提交
295
}
296
RTM_EXPORT(rtgui_widget_set_ondraw);
B
bernard.xiong 已提交
297

298
void rtgui_widget_set_onmouseclick(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
B
bernard.xiong 已提交
299
{
300
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
301

302
    widget->on_mouseclick = handler;
B
bernard.xiong 已提交
303
}
304
RTM_EXPORT(rtgui_widget_set_onmouseclick);
B
bernard.xiong 已提交
305

306
void rtgui_widget_set_onkey(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
B
bernard.xiong 已提交
307
{
308
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
309

310
    widget->on_key = handler;
B
bernard.xiong 已提交
311
}
312
RTM_EXPORT(rtgui_widget_set_onkey);
B
bernard.xiong 已提交
313

314
void rtgui_widget_set_onsize(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
B
bernard.xiong 已提交
315
{
316
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
317

318
    widget->on_size = handler;
B
bernard.xiong 已提交
319
}
320
RTM_EXPORT(rtgui_widget_set_onsize);
B
bernard.xiong 已提交
321

322
void rtgui_widget_set_oncommand(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
B
bernard.xiong 已提交
323
{
324
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
325

326
    widget->on_command = handler;
B
bernard.xiong 已提交
327
}
328
RTM_EXPORT(rtgui_widget_set_oncommand);
329
#endif
B
bernard.xiong 已提交
330 331

/**
B
bernard.xiong 已提交
332
 * @brief Focuses the widget. The focused widget is the widget which can receive the keyboard events
B
bernard.xiong 已提交
333 334 335 336 337
 * @param widget a widget
 * @note The widget has to be attached to a toplevel widget, otherwise it will have no effect
 */
void rtgui_widget_focus(rtgui_widget_t *widget)
{
338
    struct rtgui_widget *old_focus;
B
bernard.xiong 已提交
339

340
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
341

342 343
    if (!RTGUI_WIDGET_IS_FOCUSABLE(widget) || !RTGUI_WIDGET_IS_ENABLE(widget))
        return;
B
bernard.xiong 已提交
344

345 346 347
    old_focus = RTGUI_WIN(widget->toplevel)->focused_widget;
    if (old_focus == widget)
        return; /* it's the same focused widget */
B
bernard.xiong 已提交
348

349 350 351
    /* unfocused the old widget */
    if (old_focus != RT_NULL)
        rtgui_widget_unfocus(old_focus);
B
bernard.xiong 已提交
352

353 354 355
    /* set widget as focused */
    widget->flag |= RTGUI_WIDGET_FLAG_FOCUS;
    RTGUI_WIN(widget->toplevel)->focused_widget = widget;
B
bernard.xiong 已提交
356

357 358 359
    /* invoke on focus in call back */
    if (widget->on_focus_in != RT_NULL)
        widget->on_focus_in(RTGUI_OBJECT(widget), RT_NULL);
B
bernard.xiong 已提交
360
}
361
RTM_EXPORT(rtgui_widget_focus);
B
bernard.xiong 已提交
362 363 364 365 366 367 368

/**
 * @brief Unfocused the widget
 * @param widget a widget
 */
void rtgui_widget_unfocus(rtgui_widget_t *widget)
{
369

370
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
371

372 373
    if (!widget->toplevel || !RTGUI_WIDGET_IS_FOCUSED(widget))
        return;
B
bernard.xiong 已提交
374

375
    widget->flag &= ~RTGUI_WIDGET_FLAG_FOCUS;
376

377 378
    if (widget->on_focus_out != RT_NULL)
        widget->on_focus_out(RTGUI_OBJECT(widget), RT_NULL);
379

380
    RTGUI_WIN(widget->toplevel)->focused_widget = RT_NULL;
381

382 383 384 385 386 387 388 389 390 391 392
    /* Ergodic constituent widget, make child loss of focus */
    if (RTGUI_IS_CONTAINER(widget))
    {
        rtgui_list_t *node;
        rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
        {
            rtgui_widget_t *child = rtgui_list_entry(node, rtgui_widget_t, sibling);
            if (RTGUI_WIDGET_IS_HIDE(child)) continue;
            rtgui_widget_unfocus(child);
        }
    }
B
bernard.xiong 已提交
393
}
394
RTM_EXPORT(rtgui_widget_unfocus);
B
bernard.xiong 已提交
395

396
void rtgui_widget_point_to_device(rtgui_widget_t *widget, rtgui_point_t *point)
B
bernard.xiong 已提交
397
{
398
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
399

400 401 402 403 404
    if (point != RT_NULL)
    {
        point->x += widget->extent.x1;
        point->y += widget->extent.y1;
    }
B
bernard.xiong 已提交
405
}
406
RTM_EXPORT(rtgui_widget_point_to_device);
B
bernard.xiong 已提交
407

408
void rtgui_widget_rect_to_device(rtgui_widget_t *widget, rtgui_rect_t *rect)
B
bernard.xiong 已提交
409
{
410
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
411

412 413 414 415
    if (rect != RT_NULL)
    {
        rect->x1 += widget->extent.x1;
        rect->x2 += widget->extent.x1;
B
bernard.xiong 已提交
416

417 418 419
        rect->y1 += widget->extent.y1;
        rect->y2 += widget->extent.y1;
    }
B
bernard.xiong 已提交
420
}
421
RTM_EXPORT(rtgui_widget_rect_to_device);
B
bernard.xiong 已提交
422

423
void rtgui_widget_point_to_logic(rtgui_widget_t *widget, rtgui_point_t *point)
B
bernard.xiong 已提交
424
{
425
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
426

427 428 429 430 431
    if (point != RT_NULL)
    {
        point->x -= widget->extent.x1;
        point->y -= widget->extent.y1;
    }
B
bernard.xiong 已提交
432
}
433
RTM_EXPORT(rtgui_widget_point_to_logic);
B
bernard.xiong 已提交
434

435
void rtgui_widget_rect_to_logic(rtgui_widget_t *widget, rtgui_rect_t *rect)
B
bernard.xiong 已提交
436
{
437
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
438

439 440 441 442
    if (rect != RT_NULL)
    {
        rect->x1 -= widget->extent.x1;
        rect->x2 -= widget->extent.x1;
B
bernard.xiong 已提交
443

444 445 446
        rect->y1 -= widget->extent.y1;
        rect->y2 -= widget->extent.y1;
    }
B
bernard.xiong 已提交
447
}
448
RTM_EXPORT(rtgui_widget_rect_to_logic);
B
bernard.xiong 已提交
449

450
struct rtgui_win *rtgui_widget_get_toplevel(rtgui_widget_t *widget)
B
bernard.xiong 已提交
451
{
452
    rtgui_widget_t *r;
B
bernard.xiong 已提交
453

454
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
455

456 457
    if (widget->toplevel)
        return widget->toplevel;
B
bernard.xiong 已提交
458

459 460 461 462 463
    rt_kprintf("widget->toplevel not properly set\n");
    r = widget;
    /* get the toplevel widget */
    while (r->parent != RT_NULL)
        r = r->parent;
B
bernard.xiong 已提交
464

465 466
    /* set toplevel */
    widget->toplevel = RTGUI_WIN(r);
B
bernard.xiong 已提交
467

468
    return RTGUI_WIN(r);
B
bernard.xiong 已提交
469
}
470
RTM_EXPORT(rtgui_widget_get_toplevel);
B
bernard.xiong 已提交
471

472 473
rt_bool_t rtgui_widget_onupdate_toplvl(struct rtgui_object *object, struct rtgui_event *event)
{
474 475
    struct rtgui_widget *widget;
    struct rtgui_event_update_toplvl *eup;
476

477 478
    RT_ASSERT(object);
    RT_ASSERT(event);
479

480 481
    widget = RTGUI_WIDGET(object);
    eup = (struct rtgui_event_update_toplvl *)event;
482

483
    widget->toplevel = eup->toplvl;
484

485
    return RT_FALSE;
486
}
487
RTM_EXPORT(rtgui_widget_onupdate_toplvl);
488

489
rt_bool_t rtgui_widget_event_handler(struct rtgui_object *object, rtgui_event_t *event)
B
bernard.xiong 已提交
490
{
491
    RTGUI_WIDGET_EVENT_HANDLER_PREPARE;
492

493 494 495 496 497 498 499 500
    switch (event->type)
    {
    case RTGUI_EVENT_SHOW:
        return rtgui_widget_onshow(object, event);
    case RTGUI_EVENT_HIDE:
        return rtgui_widget_onhide(object, event);
    case RTGUI_EVENT_UPDATE_TOPLVL:
        return rtgui_widget_onupdate_toplvl(object, event);
501
#ifndef RTGUI_USING_SMALL_SIZE
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    case RTGUI_EVENT_PAINT:
        if (widget->on_draw != RT_NULL)
            return widget->on_draw(RTGUI_OBJECT(widget), event);
        break;

    case RTGUI_EVENT_KBD:
        if (widget->on_key != RT_NULL)
            return widget->on_key(RTGUI_OBJECT(widget), event);
        break;

    case RTGUI_EVENT_MOUSE_BUTTON:
        if (widget->on_mouseclick != RT_NULL)
            return widget->on_mouseclick(RTGUI_OBJECT(widget), event);
        break;

    case RTGUI_EVENT_COMMAND:
        if (widget->on_command != RT_NULL)
            return widget->on_command(RTGUI_OBJECT(widget), event);
        break;

    case RTGUI_EVENT_RESIZE:
        if (widget->on_size != RT_NULL)
            return widget->on_size(RTGUI_OBJECT(widget), event);
        break;
526
#endif
527 528 529
    default:
        return rtgui_object_event_handler(object, event);
    }
B
bernard.xiong 已提交
530

531
    return RT_FALSE;
B
bernard.xiong 已提交
532
}
533
RTM_EXPORT(rtgui_widget_event_handler);
B
bernard.xiong 已提交
534 535 536 537

/*
 * This function updates the clip info of widget
 */
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
void rtgui_widget_update_clip(rtgui_widget_t *widget)
{
    struct rtgui_list_node *node;
    rtgui_widget_t *parent;

    /* no widget or widget is hide, no update clip */
    if (widget == RT_NULL || RTGUI_WIDGET_IS_HIDE(widget)) return;

    parent = widget->parent;
    /* if there is no parent, there is no clip to update. */
    if (parent == RT_NULL)
    {
        return;
    }

    /* reset clip to extent */
    rtgui_region_reset(&(widget->clip), &(widget->extent));

    /* limit widget extent in parent extent */
    rtgui_region_intersect(&(widget->clip), &(widget->clip), &(parent->clip));

    /* get the no transparent parent */
    while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT)
    {
        parent = parent->parent;
    }

    if (parent != RT_NULL)
    {
        /* subtract widget clip in parent clip */
        if (!(widget->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) && RTGUI_IS_CONTAINER(parent))
        {
            rtgui_region_subtract_rect(&(parent->clip), &(parent->clip),
                                       &(widget->extent));
        }
    }

    /*
     * note: since the layout widget introduction, the sibling widget will not
     * intersect.
     */

    /* if it's a view object, update the clip info of children */
    if (RTGUI_IS_CONTAINER(widget))
    {
        rtgui_widget_t *child;
        rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
        {
            child = rtgui_list_entry(node, rtgui_widget_t, sibling);

            rtgui_widget_update_clip(child);
        }
    }
    else if (RTGUI_IS_NOTEBOOK(widget))
    {
        rtgui_widget_update_clip(rtgui_notebook_get_current(RTGUI_NOTEBOOK(widget)));
    }
B
bernard.xiong 已提交
595
}
596
RTM_EXPORT(rtgui_widget_update_clip);
B
bernard.xiong 已提交
597

598
void rtgui_widget_show(struct rtgui_widget *widget)
B
bernard.xiong 已提交
599
{
600 601
    struct rtgui_event_show eshow;
    RT_ASSERT(widget != RT_NULL);
602 603 604 605

    if (!RTGUI_WIDGET_IS_HIDE(widget))
        return;

606 607 608 609 610 611 612
    RTGUI_EVENT_SHOW_INIT(&eshow);
    if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
    {
        RTGUI_OBJECT(widget)->event_handler(
            RTGUI_OBJECT(widget),
            &eshow);
    }
613
}
614
RTM_EXPORT(rtgui_widget_show);
615 616 617

rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event)
{
618
    struct rtgui_widget *widget = RTGUI_WIDGET(object);
B
bernard.xiong 已提交
619

620
    if (!RTGUI_WIDGET_IS_HIDE(object))
D
dzzxzz@gmail.com 已提交
621 622
        return RT_FALSE;

623
    RTGUI_WIDGET_UNHIDE(widget);
624

625
    return RT_FALSE;
B
bernard.xiong 已提交
626
}
627
RTM_EXPORT(rtgui_widget_onshow);
B
bernard.xiong 已提交
628

629
rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *event)
B
bernard.xiong 已提交
630
{
631
    struct rtgui_widget *widget = RTGUI_WIDGET(object);
632

633
    if (RTGUI_WIDGET_IS_HIDE(object))
D
dzzxzz@gmail.com 已提交
634 635
        return RT_FALSE;

636 637
    /* hide this widget */
    RTGUI_WIDGET_HIDE(widget);
B
bernard.xiong 已提交
638

639 640 641
    if (widget->parent != RT_NULL)
    {
        rtgui_widget_t *parent;
642

643 644 645 646 647 648
        parent = widget->parent;
        /* get the no transparent parent */
        while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT)
        {
            parent = parent->parent;
        }
649

650 651 652
        /* union widget rect */
        rtgui_region_union_rect(&(parent->clip), &(parent->clip), &(widget->extent));
    }
653

654
    return RT_FALSE;
655
}
656
RTM_EXPORT(rtgui_widget_onhide);
657 658 659

void rtgui_widget_hide(struct rtgui_widget *widget)
{
660 661
    struct rtgui_event_hide ehide;
    RT_ASSERT(widget != RT_NULL);
662 663 664 665

    if (RTGUI_WIDGET_IS_HIDE(widget))
        return;

666 667 668 669 670 671 672
    RTGUI_EVENT_HIDE_INIT(&ehide);
    if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
    {
        RTGUI_OBJECT(widget)->event_handler(
            RTGUI_OBJECT(widget),
            &ehide);
    }
B
bernard.xiong 已提交
673
}
674
RTM_EXPORT(rtgui_widget_hide);
B
bernard.xiong 已提交
675

676
rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t *widget)
B
bernard.xiong 已提交
677
{
678
    rtgui_widget_t *parent;
679

680 681 682 683
    /* get parent widget */
    parent = widget->parent;
    while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
        parent = parent->parent;
B
bernard.xiong 已提交
684

685 686 687
    /* get parent's color */
    if (parent != RT_NULL)
        return RTGUI_WIDGET_FOREGROUND(parent);
B
bernard.xiong 已提交
688

689
    return RTGUI_WIDGET_FOREGROUND(widget);
B
bernard.xiong 已提交
690
}
691
RTM_EXPORT(rtgui_widget_get_parent_foreground);
B
bernard.xiong 已提交
692

693
rtgui_color_t rtgui_widget_get_parent_background(rtgui_widget_t *widget)
B
bernard.xiong 已提交
694
{
695 696 697 698 699 700
    rtgui_widget_t *parent;

    /* get parent widget */
    parent = widget->parent;
    while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
        parent = parent->parent;
B
bernard.xiong 已提交
701

702 703 704
    /* get parent's color */
    if (parent != RT_NULL)
        return RTGUI_WIDGET_BACKGROUND(parent);
B
bernard.xiong 已提交
705

706
    return RTGUI_WIDGET_BACKGROUND(widget);
B
bernard.xiong 已提交
707
}
708
RTM_EXPORT(rtgui_widget_get_parent_background);
B
bernard.xiong 已提交
709

710
void rtgui_widget_update(rtgui_widget_t *widget)
B
bernard.xiong 已提交
711
{
712 713 714
    struct rtgui_event_paint paint;
    RTGUI_EVENT_PAINT_INIT(&paint);
    paint.wid = RT_NULL;
B
bernard.xiong 已提交
715

716
    RT_ASSERT(widget != RT_NULL);
B
bernard.xiong 已提交
717

718 719 720
    if (RTGUI_WIDGET_IS_HIDE(widget))
        return;

721 722 723 724 725 726
    if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
    {
        RTGUI_OBJECT(widget)->event_handler(
            RTGUI_OBJECT(widget),
            &paint.parent);
    }
B
bernard.xiong 已提交
727
}
728
RTM_EXPORT(rtgui_widget_update);
B
bernard.xiong 已提交
729

730
rtgui_widget_t *rtgui_widget_get_next_sibling(rtgui_widget_t *widget)
B
bernard.xiong 已提交
731
{
732
    rtgui_widget_t *sibling = RT_NULL;
B
bernard.xiong 已提交
733

734 735 736 737
    if (widget->sibling.next != RT_NULL)
    {
        sibling = rtgui_list_entry(widget->sibling.next, rtgui_widget_t, sibling);
    }
B
bernard.xiong 已提交
738

739
    return sibling;
B
bernard.xiong 已提交
740
}
741
RTM_EXPORT(rtgui_widget_get_next_sibling);
B
bernard.xiong 已提交
742

743
rtgui_widget_t *rtgui_widget_get_prev_sibling(rtgui_widget_t *widget)
B
bernard.xiong 已提交
744
{
745 746
    struct rtgui_list_node *node;
    rtgui_widget_t *sibling, *parent;
B
bernard.xiong 已提交
747

748 749 750 751 752 753 754 755 756 757 758
    node = RT_NULL;
    sibling = RT_NULL;
    parent = widget->parent;
    if (parent != RT_NULL)
    {
        rtgui_list_foreach(node, &(RTGUI_CONTAINER(parent)->children))
        {
            if (node->next == &(widget->sibling))
                break;
        }
    }
B
bernard.xiong 已提交
759

760 761
    if (node != RT_NULL)
        sibling = rtgui_list_entry(node, rtgui_widget_t, sibling);
B
bernard.xiong 已提交
762

763
    return sibling;
B
bernard.xiong 已提交
764
}
765
RTM_EXPORT(rtgui_widget_get_prev_sibling);
B
bernard.xiong 已提交
766 767 768 769

#ifdef RTGUI_WIDGET_DEBUG
#include <rtgui/widgets/label.h>
#include <rtgui/widgets/button.h>
770
void rtgui_widget_dump(rtgui_widget_t *widget)
B
bernard.xiong 已提交
771
{
772
    struct rtgui_object *obj;
B
bernard.xiong 已提交
773

774 775
    obj = RTGUI_OBJECT(widget);
    rt_kprintf("widget type: %s ", obj->type->name);
B
bernard.xiong 已提交
776

777 778 779 780
    if (RTGUI_IS_WIN(widget) == RT_TRUE)
        rt_kprintf(":%s ", RTGUI_WIN(widget)->title);
    else if ((RTGUI_IS_LABEL(widget) == RT_TRUE) || (RTGUI_IS_BUTTON(widget) == RT_TRUE))
        rt_kprintf(":%s ", RTGUI_LABEL(widget)->text);
B
bernard.xiong 已提交
781

782 783 784
    rt_kprintf("extent(%d, %d) - (%d, %d)\n", widget->extent.x1,
               widget->extent.y1, widget->extent.x2, widget->extent.y2);
    // rtgui_region_dump(&(widget->clip));
B
bernard.xiong 已提交
785 786
}
#endif