radiobox.c 8.1 KB
Newer Older
1 2 3 4
#include <rtgui/dc.h>
#include <rtgui/rtgui_theme.h>
#include <rtgui/widgets/radiobox.h>

5 6
#define RTGUI_RADIOBOX_DEFAULT_WIDTH    100
#define RTGUI_RADIOBOX_DEFAULT_HEIGHT   20
7 8 9

static void _rtgui_radiobox_constructor(rtgui_radiobox_t *radiobox)
{
10 11 12 13 14 15 16 17 18 19 20 21 22
    rtgui_rect_t rect = {0, 0, RTGUI_RADIOBOX_DEFAULT_WIDTH, RTGUI_RADIOBOX_DEFAULT_HEIGHT};

    /* init widget and set event handler */
    RTGUI_WIDGET(radiobox)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
    RTGUI_WIDGET_TEXTALIGN(radiobox) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL;
    rtgui_widget_set_rect(RTGUI_WIDGET(radiobox), &rect);
    rtgui_object_set_event_handler(RTGUI_OBJECT(radiobox), rtgui_radiobox_event_handler);

    /* set proper of control */
    radiobox->items = RT_NULL;
    radiobox->item_count = 0;
    radiobox->item_selection = -1;
    radiobox->orient = RTGUI_HORIZONTAL;
23 24
}

25 26 27 28 29
DEFINE_CLASS_TYPE(radiobox, "radiobox",
                  RTGUI_WIDGET_TYPE,
                  _rtgui_radiobox_constructor,
                  RT_NULL,
                  sizeof(struct rtgui_radiobox));
30

31
static void rtgui_radiobox_onmouse(struct rtgui_radiobox *radiobox, struct rtgui_event_mouse *event)
32
{
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    RT_ASSERT(radiobox != RT_NULL);
    RT_ASSERT(event  != RT_NULL);

    /* widget is hide, return */
    if (RTGUI_WIDGET_IS_HIDE(radiobox) ||
            !RTGUI_WIDGET_IS_ENABLE(radiobox)) return;

    if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
            event->button & RTGUI_MOUSE_BUTTON_LEFT)
    {
        int bord_size;
        struct rtgui_rect rect;

        /* focus widgets */
        rtgui_widget_focus(RTGUI_WIDGET(radiobox));

        /* get widget physical rect */
        rtgui_widget_get_rect(RTGUI_WIDGET(radiobox), &rect);
        rtgui_widget_rect_to_device(RTGUI_WIDGET(radiobox), &rect);

        /* get board size */
        if (radiobox->orient == RTGUI_VERTICAL)
            bord_size = radiobox->item_size;
        else
        {
            struct rtgui_rect bord_rect;

            rtgui_font_get_metrics(RTGUI_WIDGET_FONT(radiobox), "H", &bord_rect);
            bord_size = rtgui_rect_height(bord_rect);
        }
        rtgui_rect_inflate(&rect, - bord_size);
        if (rtgui_rect_contains_point(&rect, event->x, event->y) != RT_EOK) return;

        if (radiobox->orient == RTGUI_VERTICAL)
        {
            int delta_y = event->y - rect.y1;
            rtgui_radiobox_set_selection(radiobox, delta_y / radiobox->item_size);
        }
        else
        {
            int delta_x = event->x - rect.x1;
            rtgui_radiobox_set_selection(radiobox, delta_x / radiobox->item_size);
        }
    }
77 78
}

79
rt_bool_t rtgui_radiobox_event_handler(struct rtgui_object *object, struct rtgui_event *event)
80
{
81 82
    struct rtgui_radiobox *radiobox;
    RTGUI_WIDGET_EVENT_HANDLER_PREPARE
83

84 85 86 87
    radiobox = RTGUI_RADIOBOX(object);
    switch (event->type)
    {
    case RTGUI_EVENT_PAINT:
88
#ifndef RTGUI_USING_SMALL_SIZE
89 90 91
        if (widget->on_draw != RT_NULL)
            widget->on_draw(RTGUI_OBJECT(widget), event);
        else
92
#endif
93 94 95
        {
            rtgui_theme_draw_radiobox(radiobox);
        }
96

97
        break;
98

99 100
    case RTGUI_EVENT_KBD:
        if (RTGUI_WIDGET_IS_HIDE(radiobox)) return RT_FALSE;
101 102

#ifndef RTGUI_USING_SMALL_SIZE
103 104 105
        if (widget->on_key != RT_NULL)
            return widget->on_key(RTGUI_OBJECT(widget), event);
        else
106
#endif
107 108
        {
            struct rtgui_event_kbd *e = (struct rtgui_event_kbd *)event;
109 110 111 112 113

            /* set focused */
            rtgui_widget_focus(RTGUI_WIDGET(radiobox));
            if (!(RTGUI_KBD_IS_UP(e))) return RT_FALSE;

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 146 147 148 149 150 151
            if (radiobox->orient == RTGUI_VERTICAL)
            {
                if (e->key == RTGUIK_UP)
                {
                    if (radiobox->item_selection > 0)
                    {
                        rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1);
                        return RT_TRUE;
                    }
                }
                else if (e->key == RTGUIK_DOWN)
                {
                    if (radiobox->item_selection < radiobox->item_count - 1)
                    {
                        rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1);
                        return RT_TRUE;
                    }
                }
            }
            else
            {
                if (e->key == RTGUIK_LEFT)
                {
                    if (radiobox->item_selection > 0)
                    {
                        rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1);
                        return RT_TRUE;
                    }
                }
                else if (e->key == RTGUIK_RIGHT)
                {
                    if (radiobox->item_selection < radiobox->item_count - 1)
                    {
                        rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1);
                        return RT_TRUE;
                    }
                }
            }
152
        }
153
        break;
154

155
    case RTGUI_EVENT_MOUSE_BUTTON:
156
#ifndef RTGUI_USING_SMALL_SIZE
157 158 159
        if (widget->on_mouseclick != RT_NULL)
            widget->on_mouseclick(RTGUI_OBJECT(widget), event);
        else
160
#endif
161 162 163 164 165 166 167 168 169
        {
            rtgui_radiobox_onmouse(radiobox, (struct rtgui_event_mouse *)event);
        }
        break;
    default:
        return rtgui_widget_event_handler(object, event);
    }

    return RT_FALSE;
170 171
}

172
struct rtgui_radiobox *rtgui_radiobox_create(const char *label, int orient, char **radio_items, int number)
173
{
174
    struct rtgui_radiobox *radiobox;
175

176
    radiobox = (struct rtgui_radiobox *) rtgui_widget_create(RTGUI_RADIOBOX_TYPE);
177 178
    if (radiobox != RT_NULL)
    {
179 180 181
        rt_uint8_t board_size;
        struct rtgui_rect rect;

182 183 184
        radiobox->items = radio_items;
        radiobox->item_count = number;
        radiobox->item_selection = -1;
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
        radiobox->text = rt_strdup(label);

        /* set proper of control */
        rtgui_radiobox_set_orientation(radiobox, orient);
        rtgui_font_get_metrics(RTGUI_WIDGET_FONT(radiobox), "H", &rect);
        board_size = rtgui_rect_height(rect);

        if (orient == RTGUI_VERTICAL)
        {
            radiobox->item_size = board_size;
        }
        else
        {
            int index;
            struct rtgui_font *font;
            struct rtgui_rect rect;

            /* set init item size */
            radiobox->item_size = 0;

            font = RTGUI_WIDGET_FONT(radiobox);
            for (index = 0; index < number; index ++)
            {
                rtgui_font_get_metrics(font, radio_items[index], &rect);
                if ((board_size + 3 + rtgui_rect_width(rect)) > radiobox->item_size)
                    radiobox->item_size = board_size + 3 + rtgui_rect_width(rect);
            }
        }

        if (radiobox->item_size < RADIO_BOX_H + 2)
            radiobox->item_size = RADIO_BOX_H + 2;
    }

    return radiobox;
219 220
}

221
void rtgui_radiobox_set_orientation(struct rtgui_radiobox *radiobox, int orientation)
222
{
223
    RT_ASSERT(radiobox != RT_NULL);
224

225 226
    /* set orientation */
    radiobox->orient = orientation;
227
#ifndef RTGUI_USING_SMALL_SIZE
228 229 230
    if (radiobox->orient == RTGUI_HORIZONTAL)
    {
        /* HORIZONTAL */
G
Grissiom 已提交
231 232
        rtgui_widget_set_minheight(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT);
        rtgui_widget_set_minwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_WIDTH);
233 234 235 236
    }
    else
    {
        /* VERTICAL */
G
Grissiom 已提交
237 238
        rtgui_widget_set_minwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT);
        rtgui_widget_set_minheight(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_WIDTH);
239
    }
240 241 242
#endif
}

243
void rtgui_radiobox_set_selection(struct rtgui_radiobox *radiobox, int selection)
244
{
245
    rt_uint16_t old_item;
246

247
    if (selection == radiobox->item_selection) return;
248

249
    old_item = radiobox->item_selection;
250 251
    if (selection >= 0 && selection < radiobox->item_count)
    {
252
        radiobox->item_selection = selection;
253 254 255
    }

    /* update radiobox widget */
256 257
    rtgui_theme_draw_radiobutton(radiobox, old_item);
    rtgui_theme_draw_radiobutton(radiobox, radiobox->item_selection);
258 259
}

260
int rtgui_radiobox_get_selection(struct rtgui_radiobox *radiobox)
261 262 263
{
    return radiobox->item_selection;
}