summaryrefslogtreecommitdiff
path: root/components/rtgui/widgets
diff options
context:
space:
mode:
author[email protected] <[email protected]>2011-06-05 15:19:19 +0000
committer[email protected] <[email protected]>2011-06-05 15:19:19 +0000
commitdb9e590b90fc8f01d708f7f67190c114fb1ef6ac (patch)
tree9e1dc68b27ba77627789099be5c127199656b3f0 /components/rtgui/widgets
parentbbf68d15e513d4799f651acd4fd9f88fe3a03ffd (diff)
add multi-text view widget.
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1455 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'components/rtgui/widgets')
-rw-r--r--components/rtgui/widgets/button.c6
-rw-r--r--components/rtgui/widgets/label.c4
-rw-r--r--components/rtgui/widgets/listbox.c19
-rw-r--r--components/rtgui/widgets/menu.c16
-rw-r--r--components/rtgui/widgets/scrollbar.c4
-rw-r--r--components/rtgui/widgets/textview.c352
6 files changed, 388 insertions, 13 deletions
diff --git a/components/rtgui/widgets/button.c b/components/rtgui/widgets/button.c
index 827590f498..9d28221b8a 100644
--- a/components/rtgui/widgets/button.c
+++ b/components/rtgui/widgets/button.c
@@ -66,11 +66,7 @@ rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_e
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_button(btn);
+ rtgui_theme_draw_button(btn);
break;
case RTGUI_EVENT_KBD:
diff --git a/components/rtgui/widgets/label.c b/components/rtgui/widgets/label.c
index 3f35dc0429..59cf22b6f4 100644
--- a/components/rtgui/widgets/label.c
+++ b/components/rtgui/widgets/label.c
@@ -95,6 +95,9 @@ void rtgui_label_set_text(rtgui_label_t* label, const char* text)
if (label->text != RT_NULL)
{
+ /* it's a same text string */
+ if (rt_strncmp(text, label->text, rt_strlen(text)) == 0) return;
+
/* release old text memory */
rt_free(label->text);
}
@@ -105,3 +108,4 @@ void rtgui_label_set_text(rtgui_label_t* label, const char* text)
/* update widget */
rtgui_theme_draw_label(label);
}
+
diff --git a/components/rtgui/widgets/listbox.c b/components/rtgui/widgets/listbox.c
index 5bb3feb8f8..cf2532771d 100644
--- a/components/rtgui/widgets/listbox.c
+++ b/components/rtgui/widgets/listbox.c
@@ -41,10 +41,10 @@ DEFINE_CLASS_TYPE(listbox, "listbox",
void rtgui_listbox_ondraw(struct rtgui_listbox* box)
{
- struct rtgui_rect rect, item_rect;
struct rtgui_dc* dc;
rt_uint16_t page_index, index;
const struct rtgui_listbox_item* item;
+ struct rtgui_rect rect, item_rect, image_rect;
dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
if (dc == RT_NULL) return;
@@ -83,7 +83,10 @@ void rtgui_listbox_ondraw(struct rtgui_listbox* box)
if (item->image != RT_NULL)
{
- rtgui_image_blit(item->image, dc, &item_rect);
+ rtgui_image_get_rect(item->image, &image_rect);
+ rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+
+ rtgui_image_blit(item->image, dc, &image_rect);
item_rect.x1 += item->image->w + 2;
}
/* draw text */
@@ -104,7 +107,7 @@ static void rtgui_listbox_update_current(struct rtgui_listbox* box, rt_int16_t o
{
struct rtgui_dc* dc;
const struct rtgui_listbox_item* item;
- rtgui_rect_t rect, item_rect;
+ rtgui_rect_t rect, item_rect, image_rect;
if ((old_item == -1) || (old_item/box->page_items != box->current_item/box->page_items))
{
@@ -134,7 +137,10 @@ static void rtgui_listbox_update_current(struct rtgui_listbox* box, rt_int16_t o
item = &(box->items[old_item]);
if (item->image != RT_NULL)
{
- rtgui_image_blit(item->image, dc, &item_rect);
+ rtgui_image_get_rect(item->image, &image_rect);
+ rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+
+ rtgui_image_blit(item->image, dc, &image_rect);
item_rect.x1 += item->image->w + 2;
}
rtgui_dc_draw_text(dc, item->name, &item_rect);
@@ -155,7 +161,10 @@ static void rtgui_listbox_update_current(struct rtgui_listbox* box, rt_int16_t o
item = &(box->items[box->current_item]);
if (item->image != RT_NULL)
{
- rtgui_image_blit(item->image, dc, &item_rect);
+ rtgui_image_get_rect(item->image, &image_rect);
+ rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+
+ rtgui_image_blit(item->image, dc, &image_rect);
item_rect.x1 += (item->image->w + 2);
}
rtgui_dc_draw_text(dc, item->name, &item_rect);
diff --git a/components/rtgui/widgets/menu.c b/components/rtgui/widgets/menu.c
index 9c1d19f73a..a68ca9e39f 100644
--- a/components/rtgui/widgets/menu.c
+++ b/components/rtgui/widgets/menu.c
@@ -81,10 +81,18 @@ static void _rtgui_menu_onitem(struct rtgui_widget* widget, struct rtgui_event*
}
else /* other menu item */
{
+ rt_ubase_t index;
+
/* invoke action */
if (menu->items[menu->items_list->current_item].on_menuaction != RT_NULL)
menu->items[menu->items_list->current_item].on_menuaction(RTGUI_WIDGET(menu), RT_NULL);
+ /* hide all of sub-menu */
+ for (index = 0; index < menu->items_count; index ++)
+ {
+ if (menu->items[index].submenu != RT_NULL)
+ rtgui_menu_hiden(menu->items[index].submenu);
+ }
rtgui_menu_hiden(menu);
}
}
@@ -138,7 +146,7 @@ static void _rtgui_menu_item_ondraw(struct rtgui_listctrl *list, struct rtgui_dc
}
DEFINE_CLASS_TYPE(menu, "menu",
- RTGUI_WIDGET_TYPE,
+ RTGUI_WIN_TYPE,
_rtgui_menu_constructor,
_rtgui_menu_destructor,
sizeof(struct rtgui_menu));
@@ -170,6 +178,9 @@ static rt_bool_t rtgui_menu_on_deactivate(rtgui_widget_t* widget, rtgui_event_t*
menu->on_menuhide(RTGUI_WIDGET(menu), RT_NULL);
}
+ /* un-select item */
+ menu->items_list->current_item = -1;
+
/* if it's a submenu, try to hide parent menu */
if (menu->parent_menu != RT_NULL &&
rtgui_win_is_activated(RTGUI_WIN(menu->parent_menu)) == RT_FALSE)
@@ -258,7 +269,10 @@ void rtgui_menu_pop(struct rtgui_menu* menu, int x, int y)
void rtgui_menu_hiden(struct rtgui_menu* menu)
{
rtgui_win_hiden(RTGUI_WIN(menu));
+ /* un-select item */
+ menu->items_list->current_item = -1;
if (menu->parent_menu != RT_NULL)
rtgui_menu_hiden(menu->parent_menu);
}
+
diff --git a/components/rtgui/widgets/scrollbar.c b/components/rtgui/widgets/scrollbar.c
index 5581ba0560..d611691cc7 100644
--- a/components/rtgui/widgets/scrollbar.c
+++ b/components/rtgui/widgets/scrollbar.c
@@ -72,7 +72,7 @@ void rtgui_scrollbar_get_thumb_rect(rtgui_scrollbar_t *bar, rtgui_rect_t *rect)
/* vertical scroll bar */
rect->x1 = scrollbar_rect.x1;
- rect->x2 = scrollbar_rect.x2;
+ rect->x2 = scrollbar_rect.x2 - 1;
rect->y1 = scrollbar_rect.y1 + btn_width + _rtgui_scrollbar_get_thumb_position(bar);
rect->y2 = rect->y1 + btn_width;
}
@@ -85,7 +85,7 @@ void rtgui_scrollbar_get_thumb_rect(rtgui_scrollbar_t *bar, rtgui_rect_t *rect)
rect->x2 = rect->x1 + btn_height;
rect->y1 = scrollbar_rect.y1;
- rect->y2 = scrollbar_rect.y2;
+ rect->y2 = scrollbar_rect.y2 - 1;
}
}
diff --git a/components/rtgui/widgets/textview.c b/components/rtgui/widgets/textview.c
new file mode 100644
index 0000000000..8540f96fb3
--- /dev/null
+++ b/components/rtgui/widgets/textview.c
@@ -0,0 +1,352 @@
+/*
+ * File : textview.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2011, 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
+ * 2011-03-05 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/textview.h>
+
+rt_inline unsigned char* _get_line_text(rtgui_textview_t *textview, rt_uint16_t index)
+{
+ unsigned char* line;
+ if (index < textview->line_count)
+ {
+ line = textview->lines + (index * textview->line_width);
+ return line;
+ }
+
+ return RT_NULL;
+}
+
+static void _calc_line(rtgui_textview_t *textview, const char* text)
+{
+ unsigned char* line;
+ const unsigned char* ptr;
+ rt_ubase_t line_index, line_position;
+
+ if (textview->lines != RT_NULL)
+ {
+ rt_free(textview->lines);
+ textview->lines = RT_NULL;
+ textview->line_count = 0;
+ }
+
+ /* get line count */
+ line_index = 0; line_position = 0;
+ ptr = (const unsigned char*)text;
+ if (*ptr == 0) return;
+
+ while (*ptr != '\0')
+ {
+ if (*ptr == '\n')
+ {
+ line_index ++;
+ line_position = 0;
+ }
+ else if (*ptr == '\r')
+ {
+ ptr ++;
+ continue;
+ }
+ else if (*ptr == '\t')
+ {
+ line_position += 4;
+ if (line_position >= textview->line_width - 1)
+ {
+ line_index ++;
+ line_position = 0;
+ }
+ }
+ else
+ {
+ if ((*ptr) >= 0x80)
+ {
+ /* fill cjk character */
+ if (line_position + 1 >= (textview->line_width - 1))
+ {
+ /* split to next line */
+ line_index ++;
+ line_position = 0;
+ }
+
+ line_position ++;
+ line_position ++;
+ }
+ else
+ {
+ line_position ++;
+ }
+
+ if (line_position >= textview->line_width - 1)
+ {
+ line_index ++;
+ line_position = 0;
+ }
+ }
+
+ ptr ++;
+ }
+
+ /* set line count */
+ textview->line_count = line_index + 1;
+
+ /* allocate lines */
+ textview->lines = rt_malloc(textview->line_count * textview->line_width);
+ rt_memset(textview->lines, 0, (textview->line_count * textview->line_width));
+
+ /* fill lines */
+ line_index = 0; line_position = 0;
+ ptr = (const unsigned char*)text;
+ line = _get_line_text(textview, line_index);
+ while (*ptr)
+ {
+ if (*ptr == '\n')
+ {
+ line_index ++;
+ line_position = 0;
+ line = _get_line_text(textview, line_index);
+ }
+ else if (*ptr == '\r')
+ {
+ /* ignore '\r' */
+ ptr ++;
+ continue;
+ }
+ else if (*ptr == '\t')
+ {
+ line[line_position++] = ' ';
+ line[line_position++] = ' ';
+ line[line_position++] = ' ';
+ line[line_position++] = ' ';
+ if (line_position >= textview->line_width - 1)
+ {
+ line_index ++;
+ line_position = 0;
+ line = _get_line_text(textview, line_index);
+ }
+ }
+ else
+ {
+ if ((*ptr) >= 0x80)
+ {
+ /* fill cjk character */
+ if (line_position + 1 >= (textview->line_width - 1))
+ {
+ /* split to next line */
+ line_index ++;
+ line_position = 0;
+ line = _get_line_text(textview, line_index);
+ }
+
+ line[line_position ++] = *ptr ++;
+ line[line_position ++] = *ptr;
+ }
+ else
+ {
+ line[line_position ++] = *ptr;
+ }
+
+ if (line_position >= textview->line_width - 1)
+ {
+ line_index ++;
+ line_position = 0;
+ line = _get_line_text(textview, line_index);
+ }
+ }
+
+ ptr ++;
+ }
+
+ textview->line_current = 0;
+}
+
+static void _calc_width(rtgui_textview_t *textview)
+{
+ rtgui_rect_t rect;
+ rt_uint16_t width, height;
+
+ width = rtgui_rect_width(RTGUI_WIDGET(textview)->extent) - 6;
+ height = rtgui_rect_height(RTGUI_WIDGET(textview)->extent);
+
+ rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &rect);
+ textview->line_width = width / rtgui_rect_width(rect) + 1;
+ textview->line_page_count = height / (rtgui_rect_height(rect) + 3);
+
+ /* set minimal value */
+ if (textview->line_page_count == 0) textview->line_page_count = 1;
+}
+
+static void _draw_textview(rtgui_textview_t *textview)
+{
+ struct rtgui_dc* dc;
+ struct rtgui_rect rect, font_rect;
+ char* line;
+ rt_ubase_t line_index, item_height;
+
+ rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &font_rect);
+ item_height = rtgui_rect_height(font_rect) + 3;
+
+ dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(textview));
+ if (dc == RT_NULL) return ;
+
+ /* fill rect */
+ rtgui_widget_get_rect(RTGUI_WIDGET(textview), &rect);
+ rtgui_dc_fill_rect(dc, &rect);
+
+ rect.x1 += 3;
+ rect.x2 -= 3;
+
+ for (line_index = textview->line_current;
+ (line_index < textview->line_current + textview->line_page_count) &&
+ (line_index < textview->line_count);
+ line_index ++)
+ {
+ line = (char* )_get_line_text(textview, line_index);
+ rtgui_dc_draw_text(dc, line, &rect);
+
+ rect.y1 += item_height;
+ }
+
+ rtgui_dc_end_drawing(dc);
+}
+
+static void _rtgui_textview_constructor(rtgui_textview_t *textview)
+{
+ /* init widget and set event handler */
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(textview), rtgui_textview_event_handler);
+ RTGUI_WIDGET(textview)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+
+ /* set field */
+ textview->line_count = 0;
+ textview->lines = RT_NULL;
+
+ textview->line_current = -1;
+ textview->line_page_count = 1;
+}
+
+static void _rtgui_textview_destructor(rtgui_textview_t *textview)
+{
+ /* release line memory */
+ rt_free(textview->lines);
+ textview->lines = RT_NULL;
+}
+
+DEFINE_CLASS_TYPE(textview, "textview",
+ RTGUI_WIDGET_TYPE,
+ _rtgui_textview_constructor,
+ _rtgui_textview_destructor,
+ sizeof(struct rtgui_textview));
+
+rt_bool_t rtgui_textview_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_textview* textview;
+
+ RT_ASSERT(widget != RT_NULL);
+
+ textview = (struct rtgui_textview*) widget;
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ _draw_textview(textview);
+ break;
+
+ case RTGUI_EVENT_KBD:
+ {
+ struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
+ if (ekbd->type == RTGUI_KEYDOWN)
+ {
+ rt_int16_t line_current_update;
+ line_current_update = textview->line_current;
+ if (ekbd->key == RTGUIK_LEFT)
+ {
+ if (textview->line_current > textview->line_page_count)
+ {
+ line_current_update -= textview->line_page_count;
+ }
+ else if (textview->line_current > 0)
+ {
+ line_current_update = 0;
+ }
+ }
+ else if (ekbd->key == RTGUIK_RIGHT)
+ {
+ if (textview->line_current + textview->line_page_count < textview->line_count - 1)
+ {
+ line_current_update += textview->line_page_count;
+ }
+ }
+ else if (ekbd->key == RTGUIK_UP)
+ {
+ if (textview->line_current > 0)
+ {
+ line_current_update --;
+ }
+ }
+ else if (ekbd->key == RTGUIK_DOWN)
+ {
+ if (textview->line_current + textview->line_page_count < textview->line_count - 1)
+ {
+ line_current_update ++;
+ }
+ }
+
+ if (textview->line_current != line_current_update)
+ {
+ textview->line_current = line_current_update;
+ rtgui_widget_update(widget);
+ return RT_TRUE;
+ }
+ }
+ break;
+ }
+ }
+
+ return RT_FALSE;
+}
+
+rtgui_textview_t* rtgui_textview_create(const char* text, const rtgui_rect_t *rect)
+{
+ struct rtgui_textview* textview;
+
+ textview = (struct rtgui_textview*) rtgui_widget_create(RTGUI_TEXTVIEW_TYPE);
+ if (textview != RT_NULL)
+ {
+ rtgui_widget_set_rect(RTGUI_WIDGET(textview), rect);
+
+ /* calculate line width and line page count */
+ _calc_width(textview);
+
+ /* set text */
+ _calc_line(textview, text);
+ }
+
+ return textview;
+}
+
+void rtgui_textview_destroy(rtgui_textview_t* textview)
+{
+ rtgui_widget_destroy(RTGUI_WIDGET(textview));
+}
+
+void rtgui_textview_set_text(rtgui_textview_t* textview, const char* text)
+{
+ RT_ASSERT(textview != RT_NULL);
+
+ /* calculate line width and line page count */
+ _calc_width(textview);
+
+ /* set text */
+ _calc_line(textview, text);
+
+ /* update widget */
+ rtgui_widget_update(RTGUI_WIDGET(textview));
+}