260 lines
6.4 KiB
C
260 lines
6.4 KiB
C
/*
|
|
* 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)
|
|
{
|
|
/* init widget and set event handler */
|
|
rtgui_object_set_event_handler(RTGUI_OBJECT(box), RT_NULL);
|
|
|
|
/* set proper of control */
|
|
box->orient = RTGUI_HORIZONTAL;
|
|
box->border_size = RTGUI_BORDER_DEFAULT_WIDTH;
|
|
box->container = RT_NULL;
|
|
}
|
|
|
|
DEFINE_CLASS_TYPE(box, "box",
|
|
RTGUI_OBJECT_TYPE,
|
|
_rtgui_box_constructor,
|
|
RT_NULL,
|
|
sizeof(struct rtgui_box));
|
|
|
|
struct rtgui_box* rtgui_box_create(int orientation, int border_size)
|
|
{
|
|
struct rtgui_box* box;
|
|
|
|
box = (struct rtgui_box*) rtgui_object_create (RTGUI_BOX_TYPE);
|
|
if (box != RT_NULL)
|
|
{
|
|
box->orient = orientation;
|
|
box->border_size = border_size;
|
|
}
|
|
|
|
return box;
|
|
}
|
|
|
|
static void rtgui_box_layout_vertical(rtgui_box_t* box)
|
|
{
|
|
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;
|
|
struct rtgui_widget *container_widget;
|
|
|
|
/* prepare the resize event */
|
|
RTGUI_EVENT_RESIZE_INIT(&size_event);
|
|
container_widget = RTGUI_WIDGET(box->container);
|
|
|
|
/* 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 ++;
|
|
else total_height += widget->mini_height;
|
|
}
|
|
|
|
/* calculate the height for each spaces */
|
|
if (space_count != 0)
|
|
{
|
|
space_height = (rtgui_rect_height(container_widget->extent) - total_height - (box->border_size << 1)) / space_count;
|
|
}
|
|
|
|
/* init (x, y) and box width */
|
|
next_x = container_widget->extent.x1 + box->border_size;
|
|
next_y = container_widget->extent.y1 + box->border_size;
|
|
box_width = rtgui_rect_width(container_widget->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);
|
|
rect->x2 = widget->mini_width;
|
|
rect->y2 = widget->mini_height;
|
|
|
|
/* 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;
|
|
}
|
|
}
|
|
|
|
static void rtgui_box_layout_horizontal(rtgui_box_t* box)
|
|
{
|
|
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;
|
|
struct rtgui_widget *container_widget;
|
|
|
|
/* prepare the resize event */
|
|
RTGUI_EVENT_RESIZE_INIT(&size_event);
|
|
container_widget = RTGUI_WIDGET(box->container);
|
|
|
|
/* 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 ++;
|
|
else total_width += widget->mini_width;
|
|
}
|
|
|
|
if (space_count != 0)
|
|
{
|
|
/* calculate the height for each spaces */
|
|
space_width = (rtgui_rect_width(container_widget->extent) - total_width) / space_count;
|
|
}
|
|
|
|
/* init (x, y) and box height */
|
|
next_x = container_widget->extent.x1 + box->border_size;
|
|
next_y = container_widget->extent.y1 + box->border_size;
|
|
box_height = rtgui_rect_height(container_widget->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);
|
|
rect->x2 = widget->mini_width;
|
|
rect->y2 = widget->mini_height;
|
|
|
|
/* 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;
|
|
}
|
|
}
|
|
|
|
void rtgui_box_layout(rtgui_box_t* box)
|
|
{
|
|
RT_ASSERT(box != RT_NULL);
|
|
|
|
if (box->container == RT_NULL) return;
|
|
|
|
if (box->orient & RTGUI_VERTICAL)
|
|
{
|
|
rtgui_box_layout_vertical(box);
|
|
}
|
|
else
|
|
{
|
|
rtgui_box_layout_horizontal(box);
|
|
}
|
|
|
|
/* update box and its children clip */
|
|
if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box->container)))
|
|
{
|
|
rtgui_widget_update_clip(RTGUI_WIDGET(box->container));
|
|
}
|
|
}
|
|
|