box.c 8.0 KB
Newer Older
B
bernard.xiong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * File      : box.c
 * This file is part of 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-16     Bernard      first version
 */
#include <rtgui/dc.h>
#include <rtgui/widgets/box.h>

static void _rtgui_box_constructor(rtgui_box_t *box)
{
19 20
    /* init widget and set event handler */
    rtgui_object_set_event_handler(RTGUI_OBJECT(box), RT_NULL);
B
bernard.xiong 已提交
21

22 23 24 25
    /* set proper of control */
    box->orient = RTGUI_HORIZONTAL;
    box->border_size = RTGUI_BORDER_DEFAULT_WIDTH;
    box->container = RT_NULL;
B
bernard.xiong 已提交
26 27
}

28
DEFINE_CLASS_TYPE(box, "box",
29 30 31 32
                  RTGUI_OBJECT_TYPE,
                  _rtgui_box_constructor,
                  RT_NULL,
                  sizeof(struct rtgui_box));
B
bernard.xiong 已提交
33

34
struct rtgui_box *rtgui_box_create(int orientation, int border_size)
B
bernard.xiong 已提交
35
{
36
    struct rtgui_box *box;
B
bernard.xiong 已提交
37

38
    box = (struct rtgui_box *) rtgui_object_create(RTGUI_BOX_TYPE);
B
bernard.xiong 已提交
39 40
    if (box != RT_NULL)
    {
41 42 43
        box->orient = orientation;
        box->border_size = border_size;
    }
B
bernard.xiong 已提交
44

45
    return box;
B
bernard.xiong 已提交
46
}
47
RTM_EXPORT(rtgui_box_create);
B
bernard.xiong 已提交
48

49
void rtgui_box_destroy(struct rtgui_box *box)
50
{
51
    rtgui_object_destroy(RTGUI_OBJECT(box));
52
}
53
RTM_EXPORT(rtgui_box_destroy);
54

55
static void rtgui_box_layout_vertical(struct rtgui_box *box, struct rtgui_rect *extent)
B
bernard.xiong 已提交
56
{
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    rtgui_list_t *node;
    rt_int32_t box_width;
    rt_int32_t space_count;
    rt_int32_t next_x, next_y;
    rt_int32_t total_height, space_height;
    struct rtgui_event_resize size_event;

    /* prepare the resize event */
    RTGUI_EVENT_RESIZE_INIT(&size_event);

    /* find spaces */
    space_count  = 0;
    total_height = 0;
    space_height = 0;

    rtgui_list_foreach(node, &(box->container->children))
    {
        rtgui_widget_t *widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
        if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
G
Grissiom 已提交
76
        else total_height += widget->min_height;
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    }

    /* calculate the height for each spaces */
    if (space_count != 0)
    {
        space_height = (rtgui_rect_height(*extent) - total_height - (box->border_size << 1)) / space_count;
    }

    /* init (x, y) and box width */
    next_x = extent->x1 + box->border_size;
    next_y = extent->y1 + box->border_size;
    box_width = rtgui_rect_width(*extent) - (box->border_size << 1);

    /* layout each widget */
    rtgui_list_foreach(node, &(box->container->children))
    {
        struct rtgui_rect *rect;
        rtgui_widget_t *widget = rtgui_list_entry(node, struct rtgui_widget, sibling);

        /* get extent of widget */
        rect = &(widget->extent);

        /* reset rect */
        rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
G
Grissiom 已提交
101 102
        rect->x2 = widget->min_width;
        rect->y2 = widget->min_height;
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

        /* left in default */
        rtgui_rect_moveto(rect, next_x, next_y);

        if (widget->align & RTGUI_ALIGN_EXPAND)
        {
            /* expand on horizontal */
            rect->x2 = rect->x1 + (rt_int16_t)box_width;
        }
        if (widget->align & RTGUI_ALIGN_CENTER_VERTICAL)
        {
            /* center */
            rt_uint32_t mid;

            mid = box_width - rtgui_rect_width(*rect);
            mid = mid / 2;

            rect->x1 = next_x + mid;
            rect->x2 = next_x + box_width - mid;
        }
        else if (widget->align & RTGUI_ALIGN_RIGHT)
        {
            /* right */
            rect->x1 = next_x + box_width - rtgui_rect_width(*rect);
            rect->x2 = next_x + box_width;
        }

        if (widget->align & RTGUI_ALIGN_STRETCH)
        {
            rect->y2 = rect->y1 + space_height;
        }

        /* process resize event */
        size_event.x = rect->x1;
        size_event.y = rect->y1;
        size_event.w = rect->x2 - rect->x1;
        size_event.h = rect->y2 - rect->y1;
        RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
                                            &size_event.parent);

        /* point to next height */
        next_y = rect->y2 + box->border_size;
    }
B
bernard.xiong 已提交
146 147
}

148
static void rtgui_box_layout_horizontal(struct rtgui_box *box, struct rtgui_rect *extent)
B
bernard.xiong 已提交
149
{
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
    rtgui_list_t *node;
    rt_int32_t box_height;
    rt_int32_t space_count;
    rt_int32_t next_x, next_y;
    rt_int32_t total_width, space_width;
    struct rtgui_event_resize size_event;

    /* prepare the resize event */
    RTGUI_EVENT_RESIZE_INIT(&size_event);

    /* find spaces */
    space_count = 0;
    total_width = 0;
    space_width = 0;

    rtgui_list_foreach(node, &(box->container->children))
    {
        rtgui_widget_t *widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
        if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
G
Grissiom 已提交
169
        else total_width += widget->min_width;
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    }

    if (space_count != 0)
    {
        /* calculate the height for each spaces */
        space_width = (rtgui_rect_width(*extent) - total_width) / space_count;
    }

    /* init (x, y) and box height */
    next_x = extent->x1 + box->border_size;
    next_y = extent->y1 + box->border_size;
    box_height = rtgui_rect_height(*extent) - (box->border_size << 1);

    /* layout each widget */
    rtgui_list_foreach(node, &(box->container->children))
    {
        rtgui_rect_t *rect;
        rtgui_widget_t *widget = rtgui_list_entry(node, struct rtgui_widget, sibling);

        /* get extent of widget */
        rect = &(widget->extent);

        /* reset rect */
        rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
G
Grissiom 已提交
194 195
        rect->x2 = widget->min_width;
        rect->y2 = widget->min_height;
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

        /* top in default */
        rtgui_rect_moveto(rect, next_x, next_y);

        if (widget->align & RTGUI_ALIGN_EXPAND)
        {
            /* expand on vertical */
            rect->y2 = rect->y1 + box_height;
        }
        if (widget->align & RTGUI_ALIGN_CENTER_HORIZONTAL)
        {
            /* center */
            rt_uint32_t mid;

            mid = box_height - rtgui_rect_height(*rect);
            mid = mid / 2;

            rect->y1 = next_y + mid;
            rect->y2 = next_y + box_height - mid;
        }
        else if (widget->align & RTGUI_ALIGN_RIGHT)
        {
            /* right */
            rect->y1 = next_y + box_height - rtgui_rect_height(*rect);
            rect->y2 = next_y + box_height;
        }

        if (widget->align & RTGUI_ALIGN_STRETCH)
        {
            rect->x2 = rect->x1 + space_width;
        }

        /* process resize event */
        size_event.x = rect->x1;
        size_event.y = rect->y1;
        size_event.w = rect->x2 - rect->x1;
        size_event.h = rect->y2 - rect->y1;
        RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
                                            &size_event.parent);

        /* point to next width */
        next_x = rect->x2 + box->border_size;
    }
B
bernard.xiong 已提交
239 240
}

241
void rtgui_box_layout(rtgui_box_t *box)
B
bernard.xiong 已提交
242
{
243
    struct rtgui_rect extent;
B
bernard.xiong 已提交
244 245
    RT_ASSERT(box != RT_NULL);

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    if (box->container == RT_NULL) return;

    rtgui_widget_get_extent(RTGUI_WIDGET(box->container), &extent);
    if (box->orient & RTGUI_VERTICAL)
    {
        rtgui_box_layout_vertical(box, &extent);
    }
    else
    {
        rtgui_box_layout_horizontal(box, &extent);
    }

    /* update box and its children clip */
    if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box->container)))
    {
        rtgui_widget_update_clip(RTGUI_WIDGET(box->container));
    }
B
bernard.xiong 已提交
263
}
264
RTM_EXPORT(rtgui_box_layout);
265

266
void rtgui_box_layout_rect(rtgui_box_t *box, struct rtgui_rect *rect)
267
{
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    RT_ASSERT(box != RT_NULL);

    if (box->container == RT_NULL) return;

    if (box->orient & RTGUI_VERTICAL)
    {
        rtgui_box_layout_vertical(box, rect);
    }
    else
    {
        rtgui_box_layout_horizontal(box, rect);
    }

    /* update box and its children clip */
    if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box->container)))
    {
        rtgui_widget_update_clip(RTGUI_WIDGET(box->container));
    }
286
}
287 288
RTM_EXPORT(rtgui_box_layout_rect);