瀏覽代碼

add more widgets.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@291 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong 15 年之前
父節點
當前提交
5939b5f6ac

+ 4 - 0
rtgui/SConscript

@@ -34,9 +34,13 @@ server/topwin.c
 widgets_src = Split("""
 widgets/box.c
 widgets/button.c
+widgets/checkbox.c
 widgets/container.c
 widgets/iconbox.c
 widgets/label.c
+widgets/progressbar.c
+widgets/slider.c
+widgets/staticline.c
 widgets/textbox.c
 widgets/title.c
 widgets/toplevel.c

+ 248 - 1
rtgui/common/rtgui_theme.c

@@ -390,7 +390,6 @@ void rtgui_theme_draw_label(rtgui_label_t* label)
 	rtgui_dc_fill_rect(dc, &rect);
 
 	/* default left and center draw */
-	rect.y1 = rect.y1 + (rtgui_rect_height(rect) - 8)/2;
 	rtgui_dc_draw_text(dc, rtgui_label_get_text(label), &rect);
 
 	/* end drawing */
@@ -423,6 +422,17 @@ void rtgui_theme_draw_textbox(rtgui_textbox_t* box)
 		rect.x1 += RTGUI_TEXTBOX_MARGIN;
 
 		rtgui_dc_draw_text(dc, box->text, &rect);
+
+		/* draw caret */
+		if (box->flag & RTGUI_TEXTBOX_CARET_SHOW)
+		{
+			rect.x1 += box->position * box->font_width;
+			rect.x2 = rect.x1 + box->font_width;
+
+			rect.y1 = rect.y2 - 3;
+
+			rtgui_dc_fill_rect(dc, &rect);
+		}
 	}
 
 	/* end drawing */
@@ -460,6 +470,243 @@ void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox)
 	rtgui_dc_end_drawing(dc);
 }
 
+void rtgui_theme_draw_checkbox(rtgui_checkbox_t* checkbox)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect, box_rect;
+
+	/* begin drawing */
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(checkbox));
+	if (dc == RT_NULL) return;
+
+	/* get rect */
+	rtgui_widget_get_rect(RTGUI_WIDGET(checkbox), &rect);
+
+    /* fill rect */
+	rtgui_dc_fill_rect(dc, &rect);
+
+	if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(checkbox)) == RT_TRUE)
+	{
+		/* draw focused border */
+		rtgui_rect_inflate(&rect, -1);
+		rtgui_dc_draw_focus_rect(dc, &rect);
+
+		rtgui_rect_inflate(&rect, 1);
+	}
+
+	/* draw check box */
+	box_rect = rect;
+	box_rect.x1 += 2;
+	box_rect.y1 += 2;
+	box_rect.x2 = rtgui_rect_height(rect) - 4;
+	box_rect.y2 = rtgui_rect_height(rect) - 4;
+
+	rtgui_dc_draw_rect(dc, &box_rect);
+	if (checkbox->status_down == RTGUI_CHECKBOX_STATUS_CHECKED)
+	{
+		rtgui_color_t save;
+
+		save = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(checkbox));
+
+		/* swap fore/back color */
+		RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(checkbox)) = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(checkbox));
+
+		rtgui_rect_inflate(&box_rect, -2);
+		rtgui_dc_fill_rect(dc, &box_rect);
+
+		/* restore saved color */
+		RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(checkbox)) = save;
+	}
+
+	/* draw text */
+	rect.x1 += rtgui_rect_height(rect) - 4 + 5;
+	rtgui_dc_draw_text(dc, rtgui_label_get_text(RTGUI_LABEL(checkbox)), &rect);
+
+	/* end drawing */
+	rtgui_dc_end_drawing(dc);
+
+	return;
+}
+
+void rtgui_theme_draw_slider(struct rtgui_slider* slider)
+{
+	/* draw button */
+	struct rtgui_dc* dc;
+	int i, xsize, x0;
+	rtgui_rect_t r, focus_rect, slider_rect, slot_rect;
+
+	/* begin drawing */
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(slider));
+	if (dc == RT_NULL) return;
+
+	/* get widget rect */
+	rtgui_widget_get_rect(RTGUI_WIDGET(slider), &focus_rect);
+	/* fill widget rect with background color */
+	rtgui_dc_fill_rect(dc, &focus_rect);
+	r = focus_rect;
+
+	if (slider->orient == RTGUI_VERTICAL)
+	{
+		rtgui_rect_inflate(&r, -1);
+		xsize = r.y2 - r.y1  + 1 - slider->thumb_width;
+		x0 = r.y1 + slider->thumb_width / 2;
+
+		/* calculate thumb position */
+		slider_rect = r;
+		slider_rect.x1 = 5;
+		slider_rect.y1 = x0 + xsize * (slider->value - slider->min) / (slider->max - slider->min) - slider->thumb_width/2;
+		slider_rect.y2  = slider_rect.y1 + slider->thumb_width;
+
+		/* calculate slot position */
+		slot_rect.y1 = x0;
+		slot_rect.y2 = x0 + xsize;
+		slot_rect.x1 = (slider_rect.x1 + slider_rect.x2) /2 -1;
+		slot_rect.x2 = slot_rect.x1 +3;
+		/* draw slot */
+		rtgui_dc_draw_border(dc, &slot_rect, RTGUI_BORDER_RAISE);
+
+		/* draw the ticks */
+		for (i = 0; i <= slider->ticks; i++)
+		{
+			int x = x0 + xsize * i / slider->ticks;
+			rtgui_dc_draw_hline(dc, 1, 3, x);
+		}
+
+		/* draw the thumb */
+		rtgui_dc_fill_rect(dc, &slider_rect);
+		rtgui_dc_draw_border(dc, &slider_rect, RTGUI_BORDER_RAISE);
+	}
+	else
+	{
+		rtgui_rect_inflate(&r, -1);
+		xsize = r.x2 - r.x1  + 1 - slider->thumb_width;
+		x0 = r.x1 + slider->thumb_width / 2;
+
+		/* calculate thumb position */
+		slider_rect = r;
+		slider_rect.y1 = 5;
+		slider_rect.x1 = x0 + xsize * (slider->value - slider->min) / (slider->max - slider->min) - slider->thumb_width/2;
+		slider_rect.x2  = slider_rect.x1 + slider->thumb_width;
+
+		/* calculate slot position */
+		slot_rect.x1 = x0;
+		slot_rect.x2 = x0 + xsize;
+		slot_rect.y1 = (slider_rect.y1 + slider_rect.y2) /2 -1;
+		slot_rect.y2 = slot_rect.y1 +3;
+		/* draw slot */
+		rtgui_dc_draw_border(dc, &slot_rect, RTGUI_BORDER_RAISE);
+
+		/* draw the ticks */
+		for (i = 0; i <= slider->ticks; i++)
+		{
+			int x = x0 + xsize * i / slider->ticks;
+			rtgui_dc_draw_vline(dc, x, 1, 3);
+		}
+
+		/* draw the thumb */
+		rtgui_dc_fill_rect(dc, &slider_rect);
+		rtgui_dc_draw_border(dc, &slider_rect, RTGUI_BORDER_RAISE);
+	}
+
+	/* draw focus */
+	if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(slider)))
+	{
+		rtgui_dc_draw_focus_rect(dc, &focus_rect);
+	}
+
+	/* end drawing */
+	rtgui_dc_end_drawing(dc);
+	return;
+}
+
+
+void rtgui_theme_draw_progressbar(struct rtgui_progressbar* bar)
+{
+	/* draw progress bar */
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect;
+    int max = bar->range;
+    int pos = bar->position;
+    int left;
+
+	/* begin drawing */
+	dc = rtgui_dc_begin_drawing(&(bar->parent));
+	if (dc == RT_NULL) return;
+
+	rtgui_widget_get_rect(&(bar->parent), &rect);
+
+	/* fill button rect with background color */
+	bar->parent.gc.background = RTGUI_RGB(212, 208, 200);
+	rtgui_dc_fill_rect(dc, &rect);
+
+    /* draw border */
+    bar->parent.gc.foreground = RTGUI_RGB(128, 128, 128);
+    rtgui_dc_draw_hline(dc, rect.x1, rect.x2 - 1, rect.y1);
+    rtgui_dc_draw_vline(dc, rect.x1, rect.y1, rect.y2 - 1);
+    bar->parent.gc.foreground = RTGUI_RGB(64, 64, 64);
+    rtgui_dc_draw_hline(dc, rect.x1, rect.x2, rect.y1 + 1);
+    rtgui_dc_draw_vline(dc, rect.x1 + 1, rect.y1, rect.y2);
+
+	bar->parent.gc.foreground = RTGUI_RGB(212, 208, 200);
+	rtgui_dc_draw_hline(dc, rect.x1, rect.x2 + 1, rect.y2);
+	rtgui_dc_draw_vline(dc, rect.x2, rect.y1, rect.y2);
+
+	bar->parent.gc.foreground = RTGUI_RGB(255, 255, 255);
+	rtgui_dc_draw_hline(dc, rect.x1 + 1, rect.x2, rect.y2 - 1);
+	rtgui_dc_draw_vline(dc, rect.x2 - 1, rect.y1 + 1, rect.y2 - 1);
+
+    /* Nothing to draw */
+    if (max == 0)
+    {
+        rtgui_dc_end_drawing(dc);
+        return;
+    }
+
+    left = max - pos;
+	rtgui_rect_inflate(&rect, -2);
+    bar->parent.gc.background = RTGUI_RGB(0, 0, 255);
+
+    if (bar->orientation == RTGUI_VERTICAL)
+    {
+        /* Vertical bar grows from bottom to top */
+        int dy = (rtgui_rect_height(rect) * left) / max;
+        rect.y1 += dy;
+        rtgui_dc_fill_rect(dc, &rect);
+    }
+    else
+    {
+        /* Horizontal bar grows from left to right */
+        rect.x2 -= (rtgui_rect_width(rect) * left) / max;
+        rtgui_dc_fill_rect(dc, &rect);
+    }
+
+	/* end drawing */
+	rtgui_dc_end_drawing(dc);
+	return;
+}
+
+void rtgui_theme_draw_staticline(struct rtgui_staticline* staticline)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect;
+	
+	/* begin drawing */
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(staticline));
+	if (dc == RT_NULL) return ;
+	rtgui_widget_get_rect(RTGUI_WIDGET(staticline), &rect);
+	
+	if (staticline->orientation == RTGUI_HORIZONTAL)
+	{
+		rtgui_dc_draw_horizontal_line(dc, rect.x1, rect.x2, rect.y1);
+	}
+	else
+	{
+		rtgui_dc_draw_vertical_line(dc, rect.x1, rect.y1, rect.y2);
+	}
+	
+	rtgui_dc_end_drawing(dc);
+}
+
 rt_uint16_t rtgui_theme_get_selected_height()
 {
 	return SELECTED_HEIGHT;

+ 8 - 0
rtgui/include/rtgui/rtgui_theme.h

@@ -21,6 +21,10 @@
 #include <rtgui/widgets/button.h>
 #include <rtgui/widgets/textbox.h>
 #include <rtgui/widgets/iconbox.h>
+#include <rtgui/widgets/checkbox.h>
+#include <rtgui/widgets/slider.h>
+#include <rtgui/widgets/progressbar.h>
+#include <rtgui/widgets/staticline.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -33,6 +37,10 @@ void rtgui_theme_draw_button(rtgui_button_t* btn);
 void rtgui_theme_draw_label(rtgui_label_t* label);
 void rtgui_theme_draw_textbox(rtgui_textbox_t* box);
 void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox);
+void rtgui_theme_draw_checkbox(rtgui_checkbox_t* checkbox);
+void rtgui_theme_draw_slider(struct rtgui_slider* slider);
+void rtgui_theme_draw_progressbar(struct rtgui_progressbar* bar);
+void rtgui_theme_draw_staticline(struct rtgui_staticline* staticline);
 
 rt_uint16_t rtgui_theme_get_selected_height(void);
 void rtgui_theme_draw_selected(struct rtgui_dc* dc, rtgui_rect_t *rect);

+ 36 - 0
rtgui/include/rtgui/widgets/checkbox.h

@@ -0,0 +1,36 @@
+#ifndef __RTGUI_CHECKBOX_H__
+#define __RTGUI_CHECKBOX_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/widget.h>
+#include <rtgui/widgets/label.h>
+
+/** Gets the type of a button */
+#define RTGUI_CHECKBOX_TYPE       (rtgui_checkbox_type_get())
+/** Casts the object to an rtgui_button */
+#define RTGUI_CHECKBOX(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_CHECKBOX_TYPE, rtgui_checkbox))
+/** Checks if the object is an rtgui_button */
+#define RTGUI_IS_CHECKBOX(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_CHECKBOX_TYPE))
+
+#define RTGUI_CHECKBOX_STATUS_CHECKED		0
+#define RTGUI_CHECKBOX_STATUS_UNCHECKED		1
+
+struct rtgui_checkbox
+{
+	/* inherit from label */
+	struct rtgui_label parent;
+
+	/* check box status */
+	rt_uint8_t status_down;
+};
+typedef struct rtgui_checkbox rtgui_checkbox_t;
+
+rtgui_type_t *rtgui_checkbox_type_get(void);
+
+rtgui_checkbox_t* rtgui_checkbox_create(unsigned char* text);
+void rtgui_checkbox_destroy(rtgui_checkbox_t* checkbox);
+
+void rtgui_checkbox_ondraw(rtgui_checkbox_t* checkbox);
+rt_bool_t rtgui_checkbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+#endif

+ 41 - 0
rtgui/include/rtgui/widgets/progressbar.h

@@ -0,0 +1,41 @@
+#ifndef __RTGUI_PROGRESSBAR_H__
+#define __RTGUI_PROGRESSBAR_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/widget.h>
+
+/** Gets the type of a progressbar */
+#define RTGUI_PROGRESSBAR_TYPE       (rtgui_progressbar_type_get())
+/** Casts the object to a rtgui_progressbar */
+#define RTGUI_PROGRESSBAR(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_PROGRESSBAR_TYPE, rtgui_progressbar_t))
+/** Checks if the object is a rtgui_progressbar */
+#define RTGUI_IS_PROGRESSBAR(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_PROGRESSBAR_TYPE))
+
+#define DEFAULT_WIDTH           100
+#define DEFAULT_HEIGHT          20
+
+struct rtgui_progressbar
+{
+	struct rtgui_widget parent;
+
+	int orientation;
+
+    int range;
+    int position;
+};
+typedef struct rtgui_progressbar rtgui_progressbar_t;
+
+rtgui_type_t *rtgui_progressbar_type_get(void);
+
+struct rtgui_progressbar* rtgui_progressbar_create(int orientation, int range, rtgui_rect_t* r);
+void rtgui_progressbar_destroy(struct rtgui_progressbar* p_bar);
+
+rt_bool_t rtgui_progressbar_event_handler(struct rtgui_widget* widget,
+                                            struct rtgui_event* event);
+
+void rtgui_progressbar_set_value(struct rtgui_progressbar *p_bar, int value);
+int rtgui_progressbar_get_value(struct rtgui_progressbar *p_bar);
+void rtgui_progressbar_set_range(struct rtgui_progressbar *p_bar, int range);
+int rtgui_progressbar_get_range(struct rtgui_progressbar *p_bar);
+
+#endif

+ 36 - 0
rtgui/include/rtgui/widgets/radiobox.h

@@ -0,0 +1,36 @@
+#ifndef __RTGUI_RADIOBOX_H__
+#define __RTGUI_RADIOBOX_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/widget.h>
+
+/** Gets the type of a radiobox */
+#define RTGUI_RADIOBOX_TYPE       (rtgui_radiobox_type_get())
+/** Casts the object to an rtgui_radiobox */
+#define RTGUI_SLIDER(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_RADIOBOX_TYPE, rtgui_radiobox_t))
+/** Checks if the object is an rtgui_radiobox */
+#define RTGUI_IS_SLIDER(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_RADIOBOX_TYPE))
+
+struct rtgui_radiobox
+{
+	struct rtgui_widget parent;
+
+	/* widget private data */
+	int orient;
+
+	char* items;
+	int item_count, item_selection;
+};
+typedef struct rtgui_radiobox rtgui_radiobox_t;
+
+rtgui_type_t *rtgui_radiobox_type_get(void);
+
+struct rtgui_radiobox* rtgui_radiobox_create(int orient, char** radio_items, int number);
+void rtgui_radiobox_destroy(struct rtgui_radiobox* radiobox);
+
+void rtgui_radiobox_set_selection(struct rtgui_radiobox* radiobox, int selection);
+int rtgui_radiobox_get_selection(struct rtgui_radiobox* radiobox);
+
+rt_bool_t rtgui_radiobox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+#endif

+ 39 - 0
rtgui/include/rtgui/widgets/slider.h

@@ -0,0 +1,39 @@
+#ifndef __RTGUI_SLIDER_H__
+#define __RTGUI_SLIDER_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/widget.h>
+
+/** Gets the type of a slider */
+#define RTGUI_SLIDER_TYPE       (rtgui_slider_type_get())
+/** Casts the object to an rtgui_slider */
+#define RTGUI_SLIDER(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_SLIDER_TYPE, rtgui_slider_t))
+/** Checks if the object is an rtgui_slider */
+#define RTGUI_IS_SLIDER(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_SLIDER_TYPE))
+
+struct rtgui_slider
+{
+	struct rtgui_widget parent;
+
+	/* widget private data */
+	rt_size_t min, max, value, ticks;
+	rt_size_t thumb_width;
+
+	int orient;
+};
+typedef struct rtgui_slider rtgui_slider_t;
+
+rtgui_type_t *rtgui_slider_type_get(void);
+
+struct rtgui_slider* rtgui_slider_create(rt_size_t min, rt_size_t max, int orient);
+void rtgui_slider_destroy(struct rtgui_slider* slider);
+
+rt_bool_t rtgui_slider_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+void rtgui_slider_set_range(struct rtgui_slider* slider, rt_size_t min, rt_size_t max);
+void rtgui_slider_set_value(struct rtgui_slider* slider, rt_size_t value);
+void rtgui_slider_set_orientation(struct rtgui_slider* slider, int orientation);
+
+rt_size_t rtgui_slider_get_value(struct rtgui_slider* slider);
+
+#endif

+ 34 - 0
rtgui/include/rtgui/widgets/staticline.h

@@ -0,0 +1,34 @@
+#ifndef __RTGUI_STATICLINE__H__
+#define __RTGUI_STATICLINE__H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/widget.h>
+
+/*
+ * the static line widget
+ */
+
+/** Gets the type of a staticline */
+#define RTGUI_STATICLINE_TYPE       (rtgui_staticline_type_get())
+/** Casts the object to an rtgui_staticline */
+#define RTGUI_STATICLINE(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_STATICLINE_TYPE, rtgui_staticline_t))
+/** Checks if the object is an rtgui_staticline */
+#define RTGUI_IS_STATICLINE(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_STATICLINE_TYPE))
+
+struct rtgui_staticline
+{
+	/* inherit from widget */
+	struct rtgui_widget parent;
+
+	int orientation;
+};
+typedef struct rtgui_staticline rtgui_staticline_t;
+
+rtgui_staticline_t *rtgui_staticline_create(int orientation);
+void rtgui_staticline_destroy(rtgui_staticline_t* staticline);
+
+rt_bool_t rtgui_staticline_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+void rtgui_staticline_set_orientation(rtgui_staticline_t* staticline, int orientation);
+
+#endif
+

+ 7 - 5
rtgui/include/rtgui/widgets/textbox.h

@@ -27,8 +27,10 @@
 #define RTGUI_TEXTBOX_DEFAULT_WIDTH		80
 #define RTGUI_TEXTBOX_DEFAULT_HEIGHT	20
 
-#define RTGUI_TEXTBOX_SINGLE		0x00
-#define RTGUI_TEXTBOX_MULTI		0x00
+#define RTGUI_TEXTBOX_SINGLE			0x00
+#define RTGUI_TEXTBOX_MULTI				0x01
+#define RTGUI_TEXTBOX_CARET_SHOW		0x10
+#define RTGUI_TEXTBOX_CARET_HIDE		0x00
 
 struct rtgui_textbox_line
 {
@@ -42,11 +44,11 @@ struct rtgui_textbox
 	/* inherit from widget */
 	struct rtgui_widget parent;
 
-	/* text box type */
-	rt_ubase_t type;
+	/* text box flag */
+	rt_uint8_t flag;
 
 	/* current line and position */
-	rt_size_t line, line_begin, position, line_length;
+	rt_uint16_t line, line_begin, position, line_length;
 
 	rt_uint8_t* text;
 	rt_size_t font_width;

+ 5 - 1
rtgui/include/rtgui/widgets/widget.h

@@ -42,7 +42,7 @@ extern "C" {
 
 #define RTGUI_WIDGET_UNFOCUS(w)			(w)->flag &= ~RTGUI_WIDGET_FLAG_FOCUS
 #define RTGUI_WIDGET_FOCUS(w)			(w)->flag |= RTGUI_WIDGET_FLAG_FOCUS
-#define RTGUI_WIDGET_IS_FOCUS(w)		((w)->flag & RTGUI_WIDGET_FLAG_FOCUS)
+#define RTGUI_WIDGET_IS_FOCUSED(w)		((w)->flag & RTGUI_WIDGET_FLAG_FOCUS)
 
 #define RTGUI_WIDGET_IS_FOCUSABLE(w) 	((w)->flag & RTGUI_WIDGET_FLAG_FOCUSABLE)
 
@@ -195,6 +195,10 @@ void rtgui_widget_show(rtgui_widget_t* widget);
 void rtgui_widget_hide(rtgui_widget_t* widget);
 void rtgui_widget_update(rtgui_widget_t* widget);
 
+/* get parent color */
+rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t* widget);
+rtgui_color_t rtgui_widget_get_parent_background(rtgui_widget_t* widget);
+
 /* get the next sibling of widget */
 rtgui_widget_t* rtgui_widget_get_next_sibling(rtgui_widget_t* widget);
 /* get the prev sibling of widget */

+ 115 - 0
rtgui/widgets/checkbox.c

@@ -0,0 +1,115 @@
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/widgets/checkbox.h>
+
+static void _rtgui_checkbox_constructor(rtgui_checkbox_t *box)
+{
+	/* init widget and set event handler */
+	RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_checkbox_event_handler);
+
+	/* set status */
+	box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED;
+
+	/* set default gc */
+	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL;
+}
+
+rtgui_type_t *rtgui_checkbox_type_get(void)
+{
+	static rtgui_type_t *checkbox_type = RT_NULL;
+
+	if (!checkbox_type)
+	{
+		checkbox_type = rtgui_type_create("checkbox", RTGUI_LABEL_TYPE,
+			sizeof(rtgui_checkbox_t), RTGUI_CONSTRUCTOR(_rtgui_checkbox_constructor), RT_NULL);
+	}
+
+	return checkbox_type;
+}
+
+rt_bool_t rtgui_checkbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	struct rtgui_checkbox* box = (struct rtgui_checkbox*)widget;
+
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_draw != RT_NULL)
+		{
+			return widget->on_draw(widget, event);
+		}
+		else
+#endif
+			rtgui_theme_draw_checkbox(box);
+		break;
+
+	case RTGUI_EVENT_MOUSE_BUTTON:
+		{
+			if (RTGUI_WIDGET_IS_ENABLE(widget) && !RTGUI_WIDGET_IS_HIDE(widget))
+			{
+				struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event;
+				if (emouse->button & RTGUI_MOUSE_BUTTON_LEFT &&
+					emouse->button & RTGUI_MOUSE_BUTTON_UP)
+				{
+					/* set focus */
+					RTGUI_WIDGET_FOCUS(widget);
+
+					if (box->status_down & RTGUI_CHECKBOX_STATUS_UNCHECKED)
+					{
+						/* check it */
+						box->status_down = RTGUI_CHECKBOX_STATUS_CHECKED;
+					}
+					else
+					{
+						/* un-check it */
+						box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED;
+					}
+				}
+
+				/* draw checkbox */
+				rtgui_theme_draw_checkbox(box);
+
+#ifndef RTGUI_USING_SMALL_SIZE
+				/* call user callback */
+				if (widget->on_mouseclick != RT_NULL)
+				{
+					return widget->on_mouseclick(widget, event);
+				}
+#endif
+			}
+
+			return RT_TRUE;
+		}
+	}
+
+	return RT_FALSE;
+}
+
+struct rtgui_checkbox* rtgui_checkbox_create(unsigned char* text)
+{
+    struct rtgui_checkbox* box;
+
+    box = (struct rtgui_checkbox*) rtgui_widget_create (RTGUI_CHECKBOX_TYPE);
+    if (box != RT_NULL)
+    {
+		rtgui_rect_t rect;
+
+		/* set default rect */
+		rtgui_font_get_metrics(rtgui_font_default(), text, &rect);
+		rect.x2 += RTGUI_BORDER_DEFAULT_WIDTH + 5 + (RTGUI_BORDER_DEFAULT_WIDTH << 1);
+		rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
+
+		rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect);
+		rtgui_label_set_text(RTGUI_LABEL(box), text);
+	}
+
+	return box;
+}
+
+void rtgui_checkbox_destroy(rtgui_checkbox_t* box)
+{
+	rtgui_widget_destroy(RTGUI_WIDGET(box));
+}
+

+ 114 - 0
rtgui/widgets/progressbar.c

@@ -0,0 +1,114 @@
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/widgets/progressbar.h>
+
+#define RTGUI_PROGRESSBAR_DEFAULT_RANGE	100
+
+static void _rtgui_progressbar_constructor(rtgui_progressbar_t *bar)
+{
+	rtgui_rect_t rect = {0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT};
+
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(bar), rtgui_progressbar_event_handler);
+	rtgui_widget_set_rect(RTGUI_WIDGET(bar), &rect);
+
+	bar->orientation = RTGUI_HORIZONTAL;
+	bar->range = RTGUI_PROGRESSBAR_DEFAULT_RANGE;
+	bar->position = 0;
+
+	/* set gc */
+	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
+}
+
+rtgui_type_t *rtgui_progressbar_type_get(void)
+{
+	static rtgui_type_t *progressbar_type = RT_NULL;
+
+	if (!progressbar_type)
+	{
+		progressbar_type = rtgui_type_create("progressbar", RTGUI_WIDGET_TYPE,
+			sizeof(rtgui_progressbar_t), RTGUI_CONSTRUCTOR(_rtgui_progressbar_constructor), RT_NULL);
+	}
+
+	return progressbar_type;
+}
+
+rt_bool_t rtgui_progressbar_event_handler(struct rtgui_widget* widget,
+                                            struct rtgui_event* event)
+{
+	struct rtgui_progressbar* bar = (struct rtgui_progressbar*)widget;
+
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
+		else
+#endif
+		{
+			rtgui_theme_draw_progressbar(bar);
+		}
+
+		break;
+	}
+
+	return RT_FALSE;
+}
+
+struct rtgui_progressbar* rtgui_progressbar_create(int orientation, int range,
+	rtgui_rect_t* r)
+{
+    struct rtgui_progressbar* bar;
+
+    bar = (struct rtgui_progressbar*) rtgui_widget_create (RTGUI_PROGRESSBAR_TYPE);
+    if (bar != RT_NULL)
+    {
+		if (r != RT_NULL)
+			rtgui_widget_set_rect(RTGUI_WIDGET(bar), r);
+
+		bar->orientation = orientation;
+        bar->range = range;
+    }
+
+    return bar;
+}
+
+void rtgui_progressbar_destroy(struct rtgui_progressbar* bar)
+{
+	rtgui_widget_destroy(RTGUI_WIDGET(bar));
+}
+
+
+void rtgui_progressbar_set_value(struct rtgui_progressbar *bar, int value)
+{
+    RT_ASSERT(bar != RT_NULL);
+
+    bar->position = value;
+
+    rtgui_theme_draw_progressbar(bar);
+    return;
+}
+
+int rtgui_progressbar_get_value(struct rtgui_progressbar *bar)
+{
+    RT_ASSERT(bar != RT_NULL);
+
+    return bar->position;
+}
+
+void rtgui_progressbar_set_range(struct rtgui_progressbar *bar, int range)
+{
+    RT_ASSERT(bar != RT_NULL);
+
+    bar->range = range;
+
+    rtgui_theme_draw_progressbar(bar);
+    return;
+}
+
+int rtgui_progressbar_get_range(struct rtgui_progressbar *bar)
+{
+    RT_ASSERT(bar != RT_NULL);
+
+    return bar->range;
+}
+

+ 228 - 0
rtgui/widgets/radiobox.c

@@ -0,0 +1,228 @@
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/widgets/radiobox.h>
+
+#define RTGUI_RADIOBOX_DEFAULT_WIDTH	100
+#define RTGUI_RADIOBOX_DEFAULT_HEIGHT	20
+
+static void _rtgui_radiobox_constructor(rtgui_radiobox_t *radiobox)
+{
+	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_set_rect(RTGUI_WIDGET(radiobox), &rect);
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(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;
+}
+
+rtgui_type_t *rtgui_radiobox_type_get(void)
+{
+	static rtgui_type_t *radiobox_type = RT_NULL;
+
+	if (!radiobox_type)
+	{
+		radiobox_type = rtgui_type_create("radiobox", RTGUI_WIDGET_TYPE,
+			sizeof(rtgui_radiobox_t), RTGUI_CONSTRUCTOR(_rtgui_radiobox_constructor), RT_NULL);
+	}
+
+	return radiobox_type;
+}
+
+static void rtgui_radiobox_onmouse(struct rtgui_radiobox* radiobox, struct rtgui_event_mouse* event)
+{
+	RT_ASSERT(radiobox != RT_NULL);
+	RT_ASSERT(event  != RT_NULL);
+
+	if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
+		event->button & RTGUI_MOUSE_BUTTON_LEFT)
+	{
+		if (radiobox->orient == RTGUI_VERTICAL)
+		{
+		}
+		else
+		{
+		}
+
+		rtgui_widget_focus(RTGUI_WIDGET(radiobox));
+	}
+}
+
+void rtgui_theme_draw_radiobox(struct rtgui_radiobox* radiobox)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_rect rect, item_rect, radio_rect;
+	rt_size_t item_height;
+
+	/* begin drawing */
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(label));
+	if (dc == RT_NULL) return;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(label), &rect);
+    rtgui_dc_fill_rect(dc, &rect);
+
+    rtgui_dc_get_text_metrix(dc, "H", &item_rect);
+    item_height = rtgui_rect_height(item_rect);
+    radio_rect.x1 = 0; radio_rect.y1 = 0;
+    radio_rect.x2 = radio_rect.x1 + item_height;
+    radio_rect.y2 = radio_rect.y1 + item_height;
+
+    /* draw box */
+    rtgui_rect_inflat(&rect, -3);
+    rtgui_dc_draw_round_rect(dc, &rect);
+    if (radiobox->text != RT_NULL)
+    {
+        /* draw group text */
+        rtgui_dc_get_text_metrix(dc, radiobox->text, &item_rect);
+        rtgui_rect_moveto(&item_rect, rect.x1 + 5, rect.y1);
+        rtgui_dc_fill_rect(dc, &item_rect);
+
+        rtgui_dc_draw_text(dc, radiobox->text, &item_rect);
+    }
+
+    /* set the first text rect */
+    item_rect = rect;
+    item_rect.x1 += 5;
+    item_rect.y1 += item_height;
+    item_rect.y2 = item_rect.y1 + item_height;
+
+    /* draw each radio button */
+    for (index = 0; index < radiobox->item_count; index ++)
+    {
+        if (text_rect.y2 > rect.y2 - item_height) break;
+
+        /* draw radio */
+        rtgui_dc_draw_circyle(dc, );
+        if (radiobox->item_selection == index)
+        {
+            rtgui_dc_draw_focus_rect(dc, );
+            rtgui_dc_fill_circyle(dc, );
+        }
+
+        /* draw text */
+        rtgui_dc_draw_text(dc, radiobox->items[index], text_rect);
+
+        text_rect.y1 += item_height;
+        text_rect.y2 += item_height;
+    }
+
+    /* end drawing */
+	rtgui_dc_end_drawing(dc);
+}
+
+rt_bool_t rtgui_radiobox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	struct rtgui_radiobox* radiobox = (struct rtgui_radiobox*)widget;
+
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
+		else
+#endif
+		{
+			rtgui_theme_draw_radiobox(radiobox);
+		}
+
+		break;
+
+	case RTGUI_EVENT_KBD:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_key != RT_NULL) widget->on_key(widget, event);
+		else
+#endif
+		{
+            struct rtgui_event_kbd *e = (struct rtgui_event_kbd*)event;
+
+            /* set focused */
+            rtgui_widget_focus(RTGUI_WIDGET(radiobox));
+            if (!(RTGUI_KBD_IS_UP(e))) return;
+
+            if (e->key == RTGUIK_UP)
+            {
+                if (radiobox->item_selection > 0)
+                    rtgui_radiobox_set_selection(radiobox->item_selection - 1);
+            }
+            else if (e->key == RTGUIK_DOWN)
+            {
+                if (radiobox->item_selection < radiobox->item_count - 1)
+                    rtgui_radiobox_set_selection(radiobox->item_selection + 1);
+            }
+        }
+		break;
+
+	case RTGUI_EVENT_MOUSE_BUTTON:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event);
+		else
+#endif
+		{
+			rtgui_radiobox_onmouse(radiobox, (struct rtgui_event_mouse*)event);
+		}
+		break;
+	}
+
+	return RT_FALSE;
+}
+
+struct rtgui_radiobox* rtgui_radiobox_create(int orient, char** radio_items, int number)
+{
+    struct rtgui_radiobox* radiobox;
+
+    radiobox = (struct rtgui_radiobox*) rtgui_widget_create (RTGUI_RADIOBOX_TYPE);
+    if (radiobox != RT_NULL)
+    {
+        radiobox->items = radio_items;
+        radiobox->item_count = number;
+        radiobox->item_selection = -1;
+
+		/* set proper of control */
+		rtgui_radiobox_set_orientation(radiobox, orient);
+	}
+
+	return radiobox;
+}
+
+void rtgui_radiobox_set_orientation(struct rtgui_radiobox* radiobox, int orientation)
+{
+	RT_ASSERT(radiobox != RT_NULL);
+
+	/* set orientation */
+	radiobox->orient = orientation;
+#ifndef RTGUI_USING_SMALL_SIZE
+	if (radiobox->orient == RTGUI_HORIZONTAL)
+	{
+		/* HORIZONTAL */
+		rtgui_widget_set_miniheight(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT);
+		rtgui_widget_set_miniwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_WIDTH);
+	}
+	else
+	{
+		/* VERTICAL */
+		rtgui_widget_set_miniwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT);
+		rtgui_widget_set_miniheight(RTGUI_WIDGET(slider), RTGUI_RADIOBOX_DEFAULT_WIDTH);
+	}
+#endif
+}
+
+void rtgui_radiobox_set_selection(struct rtgui_radiobox* radiobox, int selection)
+{
+    if (selection >= 0 && selection < radiobox->item_count)
+    {
+    	radiobox->item_selection = selection;
+    }
+
+    /* update radiobox widget */
+    rtgui_theme_draw_radiobox(radiobox);
+}
+
+int rtgui_radiobox_get_selection(struct rtgui_radiobox* radiobox)
+{
+    return radiobox->item_selection;
+}

+ 222 - 0
rtgui/widgets/slider.c

@@ -0,0 +1,222 @@
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/widgets/slider.h>
+
+#define RTGUI_SLIDER_DEFAULT_WIDTH	100
+#define RTGUI_SLIDER_DEFAULT_HEIGHT	20
+#define RTGUI_SLIDER_DEFAULT_MIN	0
+#define RTGUI_SLIDER_DEFAULT_MAX	100
+
+static void _rtgui_slider_constructor(rtgui_slider_t *slider)
+{
+	rtgui_rect_t rect = {0, 0, RTGUI_SLIDER_DEFAULT_WIDTH, RTGUI_SLIDER_DEFAULT_HEIGHT};
+
+	/* init widget and set event handler */
+	RTGUI_WIDGET(slider)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+	rtgui_widget_set_rect(RTGUI_WIDGET(slider), &rect);
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(slider), rtgui_slider_event_handler);
+
+	/* set proper of control */
+	slider->min = RTGUI_SLIDER_DEFAULT_MIN;
+	slider->max = RTGUI_SLIDER_DEFAULT_MAX;
+	slider->value = RTGUI_SLIDER_DEFAULT_MIN;
+	slider->orient = RTGUI_HORIZONTAL;
+
+	slider->ticks = 10;
+	slider->thumb_width = 8;
+}
+
+rtgui_type_t *rtgui_slider_type_get(void)
+{
+	static rtgui_type_t *slider_type = RT_NULL;
+
+	if (!slider_type)
+	{
+		slider_type = rtgui_type_create("slider", RTGUI_WIDGET_TYPE,
+			sizeof(rtgui_slider_t), RTGUI_CONSTRUCTOR(_rtgui_slider_constructor), RT_NULL);
+	}
+
+	return slider_type;
+}
+
+static void rtgui_slider_onmouse(struct rtgui_slider* slider, struct rtgui_event_mouse* event)
+{
+	RT_ASSERT(slider != RT_NULL);
+	RT_ASSERT(event  != RT_NULL);
+
+	if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
+		event->button & RTGUI_MOUSE_BUTTON_LEFT)
+	{
+		int sel;
+		int range = slider->max - slider->min;
+		int x0, xsize;
+		int x;
+		x0 = 1 + slider->thumb_width/2;
+
+		if (slider->orient == RTGUI_VERTICAL)
+		{
+			x = event->y - RTGUI_WIDGET(slider)->extent.y1;
+			x -= x0;
+			xsize = rtgui_rect_height(RTGUI_WIDGET(slider)->extent) - 2 * x0;
+		}
+		else
+		{
+			x = event->x - RTGUI_WIDGET(slider)->extent.x1;
+			x -= x0;
+			xsize = rtgui_rect_width(RTGUI_WIDGET(slider)->extent) - 2 * x0;
+		}
+
+		if (x <= 0)
+		{
+			sel = slider->min;
+		}
+		else if (x >= xsize)
+		{
+			sel = slider->max;
+		}
+		else
+		{
+			sel = ((range * x) + xsize/2) / xsize;
+			sel += slider->min;
+		}
+
+		rtgui_widget_focus(RTGUI_WIDGET(slider));
+		rtgui_slider_set_value(slider, sel);
+	}
+}
+
+static void rtgui_slider_onkey(struct rtgui_slider* slider, struct rtgui_event_kbd *event)
+{
+	RT_ASSERT(slider != RT_NULL);
+	RT_ASSERT(event != RT_NULL);
+
+	if (!(RTGUI_KBD_IS_UP(event))) return;
+
+	if (event->key == RTGUIK_LEFT)
+	{
+		if (slider->value > slider->min)
+			slider->value ++;
+	}
+
+	if (event->key == RTGUIK_RIGHT)
+	{
+		if (slider->value < slider->max)
+			slider->value --;
+	}
+
+	/* update widget */
+	rtgui_widget_update(RTGUI_WIDGET(slider));
+}
+
+rt_bool_t rtgui_slider_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	struct rtgui_slider* slider = (struct rtgui_slider*)widget;
+
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
+		else
+#endif
+		{
+			rtgui_theme_draw_slider(slider);
+		}
+
+		break;
+
+	case RTGUI_EVENT_KBD:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_key != RT_NULL) widget->on_key(widget, event);
+		else
+#endif
+		{
+			rtgui_slider_onkey(slider, (struct rtgui_event_kbd *)event);
+		}
+		break;
+
+	case RTGUI_EVENT_MOUSE_BUTTON:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event);
+		else
+#endif
+		{
+			rtgui_slider_onmouse(slider, (struct rtgui_event_mouse*)event);
+		}
+		break;
+	}
+
+	return RT_FALSE;
+}
+
+struct rtgui_slider* rtgui_slider_create(rt_size_t min, rt_size_t max, int orient)
+{
+    struct rtgui_slider* slider;
+
+    slider = (struct rtgui_slider*) rtgui_widget_create (RTGUI_SLIDER_TYPE);
+    if (slider != RT_NULL)
+    {
+		/* set proper of control */
+		slider->min = min;
+		slider->max = max;
+		slider->value = min;
+
+		slider->ticks = 10;
+		slider->thumb_width = 8;
+
+		rtgui_slider_set_orientation(slider, orient);
+	}
+
+	return slider;
+}
+
+void rtgui_slider_set_range(struct rtgui_slider* slider, rt_size_t min, rt_size_t max)
+{
+	RT_ASSERT(slider != RT_NULL);
+
+	slider->max = max;
+	slider->min = min;
+}
+
+void rtgui_slider_set_value(struct rtgui_slider* slider, rt_size_t value)
+{
+	RT_ASSERT(slider != RT_NULL);
+
+	if (value < slider->min) value = slider->min;
+	if (value > slider->max) value = slider->max;
+
+	if (slider->value != value)
+	{
+		slider->value = value;
+		rtgui_theme_draw_slider(slider);
+	}
+}
+
+void rtgui_slider_set_orientation(struct rtgui_slider* slider, int orientation)
+{
+	RT_ASSERT(slider != RT_NULL);
+
+	/* set orientation */
+	slider->orient = orientation;
+#ifndef RTGUI_USING_SMALL_SIZE
+	if (slider->orient == RTGUI_HORIZONTAL)
+	{
+		/* HORIZONTAL */
+		rtgui_widget_set_miniheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT);
+		rtgui_widget_set_miniwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH);
+	}
+	else 
+	{
+		/* VERTICAL */
+		rtgui_widget_set_miniwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT);
+		rtgui_widget_set_miniheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH);
+	}
+#endif
+}
+
+rt_size_t rtgui_slider_get_value(struct rtgui_slider* slider)
+{
+	RT_ASSERT(slider != RT_NULL);
+
+	return slider->value;
+}

+ 89 - 0
rtgui/widgets/staticline.c

@@ -0,0 +1,89 @@
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/widgets/staticline.h>
+
+static void _rtgui_staticline_constructor(rtgui_staticline_t *staticline)
+{
+	/* init widget and set event handler */
+	rtgui_rect_t rect = {0, 0, 100, 2};
+
+	rtgui_widget_set_rect(RTGUI_WIDGET(staticline), &rect);
+	staticline->orientation= RTGUI_HORIZONTAL;
+
+	/* set background color */
+	RTGUI_WIDGET(staticline)->gc.background = RTGUI_RGB(64, 64, 64);
+
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(staticline), rtgui_staticline_event_handler);
+}
+
+rtgui_type_t *rtgui_staticline_type_get(void)
+{
+	static rtgui_type_t *staticline_type = RT_NULL;
+
+	if (!staticline_type)
+	{
+		staticline_type = rtgui_type_create("staticline", RTGUI_WIDGET_TYPE,
+			sizeof(rtgui_staticline_t), RTGUI_CONSTRUCTOR(_rtgui_staticline_constructor), RT_NULL);
+	}
+
+	return staticline_type;
+}
+
+rt_bool_t rtgui_staticline_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	struct rtgui_staticline* staticline;
+	RT_ASSERT(widget != RT_NULL);
+
+	staticline = (struct rtgui_staticline*) widget;
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
+		else
+#endif
+			rtgui_theme_draw_staticline(staticline);
+		break;
+	}
+
+	return RT_FALSE;
+}
+
+rtgui_staticline_t * rtgui_staticline_create(int orientation)
+{
+	rtgui_staticline_t* staticline;
+
+	staticline = (struct rtgui_staticline*) rtgui_widget_create(RTGUI_STATICLINE_TYPE);
+	if (staticline!= RT_NULL)
+	{
+		rtgui_staticline_set_orientation(staticline, orientation);
+	}
+
+	return staticline;
+}
+
+void rtgui_staticline_destroy(rtgui_staticline_t* staticline)
+{
+	rtgui_widget_destroy(RTGUI_WIDGET(staticline));
+}
+
+void rtgui_staticline_set_orientation(rtgui_staticline_t* staticline, int orientation)
+{
+	RT_ASSERT(staticline != RT_NULL);
+
+	staticline->orientation = orientation;
+#ifndef RTGUI_USING_SMALL_SIZE
+	if (orientation == RTGUI_HORIZONTAL)
+	{
+		/* HORIZONTAL */
+		rtgui_widget_set_miniheight(RTGUI_WIDGET(staticline), 2);
+		rtgui_widget_set_miniwidth(RTGUI_WIDGET(staticline), 100);
+	}
+	else
+	{
+		/* VERTICAL */
+		rtgui_widget_set_miniwidth(RTGUI_WIDGET(staticline), 2);
+		rtgui_widget_set_miniheight(RTGUI_WIDGET(staticline), 100);
+	}
+#endif
+}

+ 16 - 6
rtgui/widgets/textbox.c

@@ -13,7 +13,7 @@
  */
 #include <rtgui/dc.h>
 #include <rtgui/rtgui_theme.h>
-#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_system.h>
 #include <rtgui/widgets/textbox.h>
 
 #ifndef _WIN32
@@ -30,9 +30,17 @@ static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtg
 static void _rtgui_textbox_caret_timeout(struct rtgui_timer* timer, void* parameter)
 {
 	rtgui_textbox_t* box;
-
-	box = (rtgui_textbox_t*)parameter;
 	
+	box = (rtgui_textbox_t*)parameter;
+	/* set caret flag */
+	if (box->flag & RTGUI_TEXTBOX_CARET_SHOW)
+		box->flag &= ~RTGUI_TEXTBOX_CARET_SHOW;
+	else
+		box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
+
+	/* re-darw textbox */
+	rtgui_theme_draw_textbox(box);
+
 	return ;
 }
 
@@ -54,7 +62,7 @@ static void _rtgui_textbox_constructor(rtgui_textbox_t *box)
 		_rtgui_textbox_caret_timeout, box);
 
 	box->line = box->line_begin = box->position = 0;
-	box->type = RTGUI_TEXTBOX_SINGLE;
+	box->flag = RTGUI_TEXTBOX_SINGLE;
 
 	/* allocate default line buffer */
 	box->text = RT_NULL;
@@ -131,7 +139,7 @@ static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kb
 	RT_ASSERT(box != RT_NULL);
 	RT_ASSERT(event != RT_NULL);
 
-	if (event->type != RTGUI_KEYDOWN)
+	if (event->type != RTGUI_KEYUP)
 		return ;
 
 	length = rt_strlen((const char*)box->text);
@@ -217,6 +225,9 @@ static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kb
 		}
 	}
 
+	/* set caret to show */
+	box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
+
 	/* re-draw text box */
 	rtgui_theme_draw_textbox(box);
 }
@@ -289,7 +300,6 @@ struct rtgui_textbox* rtgui_textbox_create(const char* text)
 		rtgui_textbox_set_value(box, text);
 
 		rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect);
-		box->font_width = rtgui_rect_width(rect);
 	}
 
 	return box;

+ 33 - 1
rtgui/widgets/widget.c

@@ -293,7 +293,7 @@ void rtgui_widget_unfocus(rtgui_widget_t *widget)
 
 	widget->flag &= ~RTGUI_WIDGET_FLAG_FOCUS;
 
-	if (!widget->toplevel || !RTGUI_WIDGET_IS_FOCUS(widget))
+	if (!widget->toplevel || !RTGUI_WIDGET_IS_FOCUSED(widget))
 		return;
 
 #ifndef RTGUI_USING_SMALL_SIZE
@@ -480,6 +480,38 @@ void rtgui_widget_hide(rtgui_widget_t* widget)
 	rtgui_widget_update_clip(widget->parent);
 }
 
+rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t* widget)
+{
+	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;
+
+	/* get parent's color */
+	if (parent != RT_NULL)
+		return RTGUI_WIDGET_FOREGROUND(parent);
+
+	return RTGUI_WIDGET_FOREGROUND(widget);
+}
+
+rtgui_color_t rtgui_widget_get_parent_background(rtgui_widget_t* widget)
+{
+	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;
+
+	/* get parent's color */
+	if (parent != RT_NULL)
+		return RTGUI_WIDGET_BACKGROUND(parent);
+
+	return RTGUI_WIDGET_BACKGROUND(widget);
+}
+
 void rtgui_widget_update(rtgui_widget_t* widget)
 {
 	struct rtgui_event_paint paint;