chaos.proton@gmail.com db06460208 merge new RTGUI in to trunk
The full log is at https://github.com/RTGUI/RTGUI/commits/merge_1 and it's difficult to merge the new tree commit by commit. I also converted all the file into unix eol so there are many fake diff. Big changes are noted in rtgui/doc/road_map.txt and rtgui/doc/attention.txt. Keep an eye on them if you want to migrate your old code.

Note that the work is still in progress and the bsp is not prepared in trunk so far.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2092 bbd45198-f89e-11dd-88c7-29a3b14d5316
2012-04-18 15:06:12 +00:00

352 lines
7.6 KiB
C

/*
* 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 char* _get_line_text(rtgui_textview_t *textview, rt_uint16_t index)
{
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)
{
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_object_set_event_handler(RTGUI_OBJECT(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_object* object, struct rtgui_event* event)
{
struct rtgui_textview* textview;
RTGUI_WIDGET_EVENT_HANDLER_PREPARE
textview = RTGUI_TEXTVIEW(object);
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));
}