From 3f319a875c675b9ffef093312de8204247f09d59 Mon Sep 17 00:00:00 2001 From: "bernard.xiong" Date: Sat, 15 May 2010 14:36:02 +0000 Subject: [PATCH] add icon display mode in listview. git-svn-id: https://rt-thread.googlecode.com/svn/trunk@710 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- components/rtgui/common/font_hz_bmp.c | 5 +- components/rtgui/common/font_hz_file.c | 3 +- components/rtgui/common/rtgui_system.c | 8 + components/rtgui/include/rtgui/rtgui_config.h | 37 +- .../include/rtgui/widgets/filelist_view.h | 2 +- .../rtgui/include/rtgui/widgets/list_view.h | 14 +- .../rtgui/include/rtgui/widgets/listbox.h | 2 + components/rtgui/widgets/filelist_view.c | 256 +++++++--- components/rtgui/widgets/list_view.c | 440 +++++++++++++++--- components/rtgui/widgets/listbox.c | 22 +- components/rtgui/widgets/window.c | 4 +- 11 files changed, 631 insertions(+), 162 deletions(-) diff --git a/components/rtgui/common/font_hz_bmp.c b/components/rtgui/common/font_hz_bmp.c index 1190cb473c..5e025e0b78 100644 --- a/components/rtgui/common/font_hz_bmp.c +++ b/components/rtgui/common/font_hz_bmp.c @@ -16,7 +16,7 @@ struct rtgui_font_engine hz_bmp_font_engine = static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect) { - rt_base_t h; + register rt_base_t h, word_bytes; rt_uint8_t* str; struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data); @@ -24,6 +24,7 @@ static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui /* drawing height */ h = (bmp_font->height + rect->y1 > rect->y2)? rect->y2 - rect->y1 : bmp_font->height; + word_bytes = (bmp_font->width + 7)/8; str = (rt_uint8_t*)text; @@ -43,7 +44,7 @@ static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui /* draw word */ for (i=0; i < h; i ++) { - for (j=0; j < 2; j++) + for (j=0; j < word_bytes; j++) for (k=0; k < 8; k++) { if ( ((font_ptr[i*2 + j] >> (7-k)) & 0x01) != 0 && diff --git a/components/rtgui/common/font_hz_file.c b/components/rtgui/common/font_hz_file.c index e76439b55a..9a4b6380cb 100644 --- a/components/rtgui/common/font_hz_file.c +++ b/components/rtgui/common/font_hz_file.c @@ -93,7 +93,7 @@ static void rtgui_hz_file_font_load(struct rtgui_font* font) static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect) { - rt_base_t h; + register rt_base_t h, word_bytes; rt_uint8_t* str; struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data; RT_ASSERT(hz_file_font != RT_NULL); @@ -101,6 +101,7 @@ static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_d /* drawing height */ h = (hz_file_font->font_size + rect->y1 > rect->y2)? rect->y2 - rect->y1 : hz_file_font->font_size; + word_bytes = (hz_file_font->font_size + 7) / 8; str = (rt_uint8_t*)text; diff --git a/components/rtgui/common/rtgui_system.c b/components/rtgui/common/rtgui_system.c index 55cecf8bb3..dc5df0c1f2 100644 --- a/components/rtgui/common/rtgui_system.c +++ b/components/rtgui/common/rtgui_system.c @@ -125,6 +125,14 @@ static void rtgui_event_dump(rt_thread_t tid, rtgui_event_t* event) } break; + case RTGUI_EVENT_KBD: + { + struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd*) event; + if (ekbd->wid != RT_NULL) + rt_kprintf("win: %s", ekbd->wid->title); + } + break; + case RTGUI_EVENT_CLIP_INFO: { struct rtgui_event_clip_info *info = (struct rtgui_event_clip_info *)event; diff --git a/components/rtgui/include/rtgui/rtgui_config.h b/components/rtgui/include/rtgui/rtgui_config.h index a941ad6422..cb6fa8c373 100644 --- a/components/rtgui/include/rtgui/rtgui_config.h +++ b/components/rtgui/include/rtgui/rtgui_config.h @@ -19,25 +19,26 @@ /* RTGUI options */ #ifdef _WIN32 -/* name length of RTGUI object */ -#define RTGUI_NAME_MAX 12 -/* support 16 weight font */ -#define RTGUI_USING_FONT16 -/* support Chinese font */ -#define RTGUI_USING_FONTHZ -/* use small size in RTGUI */ -#define RTGUI_USING_SMALL_SIZE -/* use mouse cursor */ -/* #define RTGUI_USING_MOUSE_CURSOR */ -/* default font size in RTGUI */ -#define RTGUI_DEFAULT_FONT_SIZE 12 + /* name length of RTGUI object */ + #define RTGUI_NAME_MAX 12 + /* support 16 weight font */ + #define RTGUI_USING_FONT16 + /* support Chinese font */ + #define RTGUI_USING_FONTHZ + /* use small size in RTGUI */ + #define RTGUI_USING_SMALL_SIZE + /* use mouse cursor */ + /* #define RTGUI_USING_MOUSE_CURSOR */ + /* default font size in RTGUI */ + #define RTGUI_DEFAULT_FONT_SIZE 12 -#define RTGUI_USING_STDIO_FILERW -#define RTGUI_IMAGE_PNG -#define RTGUI_IMAGE_JPEG -#define RTGUI_USING_FONT12 -#define RTGUI_USING_HZ_BMP -#define RTGUI_MEM_TRACE + #define RTGUI_USING_STDIO_FILERW + #define RTGUI_IMAGE_PNG + #define RTGUI_IMAGE_JPEG + #define RTGUI_USING_FONT12 + #define RTGUI_USING_HZ_BMP + #define RTGUI_MEM_TRACE + #define RTGUI_USING_WINMOVE #endif #if RTGUI_DEFAULT_FONT_SIZE == 0 diff --git a/components/rtgui/include/rtgui/widgets/filelist_view.h b/components/rtgui/include/rtgui/widgets/filelist_view.h index 8f608e6de1..105b9f3554 100644 --- a/components/rtgui/include/rtgui/widgets/filelist_view.h +++ b/components/rtgui/include/rtgui/widgets/filelist_view.h @@ -51,6 +51,6 @@ void rtgui_filelist_view_destroy(rtgui_filelist_view_t* view); rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); void rtgui_filelist_view_set_directory(rtgui_filelist_view_t* view, const char* directory); -void rtgui_filelist_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len); +void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len); #endif diff --git a/components/rtgui/include/rtgui/widgets/list_view.h b/components/rtgui/include/rtgui/widgets/list_view.h index 6d7732f491..2d3b2bf6d2 100644 --- a/components/rtgui/include/rtgui/widgets/list_view.h +++ b/components/rtgui/include/rtgui/widgets/list_view.h @@ -38,6 +38,10 @@ struct rtgui_list_item /** Checks if the object is a filelist view */ #define RTGUI_IS_LIST_VIEW(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LIST_VIEW_TYPE)) +#define RTGUI_LIST_VIEW_LIST 0x00 +#define RTGUI_LIST_VIEW_ICON 0x01 +#define RTGUI_LIST_VIEW_REPORT 0x02 + struct rtgui_list_view { struct rtgui_view parent; @@ -46,19 +50,25 @@ struct rtgui_list_view /* list item */ const struct rtgui_list_item* items; + /* layout flag */ + rt_uint16_t flag; + /* total number of items */ rt_uint16_t items_count; /* the number of item in a page */ rt_uint16_t page_items; - /* current item */ + /* current item */ rt_uint16_t current_item; + + /* icon layout */ + rt_uint8_t row_items, col_items; }; typedef struct rtgui_list_view rtgui_list_view_t; rtgui_type_t *rtgui_list_view_type_get(void); rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count, - rtgui_rect_t *rect); + rtgui_rect_t *rect, rt_uint16_t flag); void rtgui_list_view_destroy(rtgui_list_view_t* view); rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); diff --git a/components/rtgui/include/rtgui/widgets/listbox.h b/components/rtgui/include/rtgui/widgets/listbox.h index 3d05e70e28..1777920b00 100644 --- a/components/rtgui/include/rtgui/widgets/listbox.h +++ b/components/rtgui/include/rtgui/widgets/listbox.h @@ -61,6 +61,8 @@ rtgui_listbox_t* rtgui_listbox_create(const struct rtgui_listbox_item* items, rt void rtgui_listbox_destroy(rtgui_listbox_t* box); rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); +void rtgui_listbox_set_onitem(rtgui_listbox_t* box, rtgui_onitem_func_t func); +void rtgui_listbox_set_items(rtgui_listbox_t* box, struct rtgui_listbox_item* items, rt_uint16_t count); #endif diff --git a/components/rtgui/widgets/filelist_view.c b/components/rtgui/widgets/filelist_view.c index 8d75f9b56d..90a0c9e672 100644 --- a/components/rtgui/widgets/filelist_view.c +++ b/components/rtgui/widgets/filelist_view.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #ifdef _WIN32 #include @@ -219,8 +221,96 @@ const static char * folder_xpm[] = { /* image for file and folder */ static rtgui_image_t *file_image, *folder_image; +static struct rtgui_listbox_item items[] = +{ + {"打开文件夹", RT_NULL}, + {"选择文件夹", RT_NULL}, + {"退出", RT_NULL} +}; static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view); +static void rtgui_filelist_view_on_folder_item(rtgui_widget_t* widget, struct rtgui_event* event) +{ + rtgui_win_t *menu; + rtgui_listbox_t *listbox; + rtgui_filelist_view_t *view; + + listbox = RTGUI_LISTBOX(widget); + menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget)); + view = RTGUI_FILELIST_VIEW(menu->user_data); + + /* hide window */ + rtgui_win_hiden(menu); + + switch (listbox->current_item) + { + case 0: + { + char* dir_ptr; + + /* destroy menu window */ + rtgui_win_destroy(menu); + + dir_ptr = (char*) rtgui_malloc (256); + rtgui_filelist_view_get_fullpath(view, dir_ptr, 256); + rtgui_filelist_view_set_directory(view, dir_ptr); + rt_free(dir_ptr); + } + break; + case 1: + /* destroy menu window */ + rtgui_win_destroy(menu); + if (RTGUI_VIEW(view)->modal_show == RT_TRUE) + { + rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK); + } + break; + + default: + /* destroy menu window */ + rtgui_win_destroy(menu); + break; + } +} + +static rt_bool_t rtgui_filelist_view_on_menu_deactivate(rtgui_widget_t* widget, struct rtgui_event* event) +{ + rtgui_win_t *menu; + menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget)); + + /* destroy menu window */ + rtgui_win_destroy(menu); + + return RT_TRUE; +} + +static void rtgui_filelist_view_menu_pop(rtgui_widget_t *parent) +{ + rtgui_win_t *menu; + rtgui_listbox_t *listbox; + rtgui_rect_t screen, rect = {0, 0, 140, 85}; + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen); + rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL); + + menu = rtgui_win_create(RTGUI_TOPLEVEL(rtgui_widget_get_toplevel(parent)), + "Folder Menu", &rect, RTGUI_WIN_STYLE_DEFAULT); + if (menu != RT_NULL) + { + /* set user data on menu window */ + menu->user_data = (rt_uint32_t)parent; + + rtgui_win_set_ondeactivate(menu, rtgui_filelist_view_on_menu_deactivate); + + listbox = rtgui_listbox_create(items, sizeof(items)/sizeof(items[0]), &rect); + rtgui_listbox_set_onitem(listbox, rtgui_filelist_view_on_folder_item); + rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(listbox)); + rtgui_widget_focus(RTGUI_WIDGET(listbox)); + + rtgui_win_show(menu, RT_FALSE); + } +} + static void _rtgui_filelist_view_constructor(struct rtgui_filelist_view *view) { /* default rect */ @@ -390,6 +480,65 @@ void rtgui_filelist_view_update_current(struct rtgui_filelist_view* view, rt_uin rtgui_dc_end_drawing(dc); } +static void rtgui_filelist_view_onenturn(struct rtgui_filelist_view* view) +{ + if (view->items[view->current_item].type == RTGUI_FITEM_DIR) + { + char new_path[64]; + + if (strcmp(view->items[view->current_item].name, ".") == 0) return ; + if (strcmp(view->items[view->current_item].name, "..") == 0) + { + char *ptr; + ptr = strrchr(view->current_directory, PATH_SEPARATOR); + + if (ptr == RT_NULL) return ; + if (ptr == &(view->current_directory[0])) + { + /* it's root directory */ + new_path[0] = PATH_SEPARATOR; + new_path[1] = '\0'; + } + else + { + strncpy(new_path, view->current_directory, ptr - view->current_directory + 1); + new_path[ptr - view->current_directory] = '\0'; + } + } + else if (view->current_item == 0 && +#ifdef _WIN32 + (view->current_directory[1] == ':') && (view->current_directory[2] == '\\')) +#else + (view->current_directory[0] == '/') && (view->current_directory[1] == '\0')) +#endif + { + if (RTGUI_VIEW(view)->modal_show == RT_TRUE) + { + rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_CANCEL); + } + else + { + rtgui_filelist_view_destroy(view); + } + + return ; + } + else + { + rtgui_filelist_view_menu_pop(RTGUI_WIDGET(view)); + return ; + } + rtgui_filelist_view_set_directory(view, new_path); + } + else + { + if (RTGUI_VIEW(view)->modal_show == RT_TRUE) + { + rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK); + } + } +} + rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) { struct rtgui_filelist_view* view = RT_NULL; @@ -431,18 +580,31 @@ rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) { rt_uint16_t index; + rt_uint16_t current_page; + rt_uint16_t old_item; + index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); + + /* get current page */ + current_page = view->current_item/view->page_items; + old_item = view->current_item; - if ((index < view->items_count) && (index < view->page_items)) + if (index + current_page * view->page_items < view->items_count) { - rt_uint16_t old_item; - - old_item = view->current_item; - /* set selected item */ - view->current_item = (old_item/view->page_items) * view->page_items + index; - rtgui_filelist_view_update_current(view, old_item); + view->current_item = index + current_page * view->page_items; + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + rtgui_filelist_view_update_current(view, old_item); + } + else + { + /* up event */ + rtgui_filelist_view_onenturn(view); + } } + + return RT_TRUE; } } break; @@ -461,87 +623,29 @@ rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct if (view->current_item > 0) view->current_item --; rtgui_filelist_view_update_current(view, old_item); - return RT_FALSE; + return RT_TRUE; case RTGUIK_DOWN: if (view->current_item < view->items_count - 1) view->current_item ++; rtgui_filelist_view_update_current(view, old_item); - return RT_FALSE; + return RT_TRUE; case RTGUIK_LEFT: if (view->current_item - view->page_items >= 0) view->current_item -= view->page_items; rtgui_filelist_view_update_current(view, old_item); - return RT_FALSE; + return RT_TRUE; case RTGUIK_RIGHT: if (view->current_item + view->page_items < view->items_count - 1) view->current_item += view->page_items; rtgui_filelist_view_update_current(view, old_item); - return RT_FALSE; + return RT_TRUE; case RTGUIK_RETURN: - if (view->items[view->current_item].type == RTGUI_FITEM_DIR) - { - char new_path[64]; - - if (strcmp(view->items[view->current_item].name, ".") == 0) return RT_FALSE; - if (strcmp(view->items[view->current_item].name, "..") == 0) - { - char *ptr; - ptr = strrchr(view->current_directory, PATH_SEPARATOR); - - if (ptr == RT_NULL) return RT_FALSE; - if (ptr == &(view->current_directory[0])) - { - /* it's root directory */ - new_path[0] = PATH_SEPARATOR; - new_path[1] = '\0'; - } - else - { - strncpy(new_path, view->current_directory, ptr - view->current_directory + 1); - new_path[ptr - view->current_directory] = '\0'; - } - } - else if (view->current_item == 0 && -#ifdef _WIN32 - (view->current_directory[1] == ':') && (view->current_directory[2] == '\\')) -#else - (view->current_directory[0] == '/') && (view->current_directory[1] == '\0')) -#endif - { - if (RTGUI_VIEW(view)->modal_show == RT_TRUE) - { - rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_CANCEL); - } - else - { - rtgui_filelist_view_destroy(view); - } - - return RT_FALSE; - } - else - { - if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR) - rt_snprintf(new_path, sizeof(new_path), "%s%c%s",view->current_directory, PATH_SEPARATOR, - view->items[view->current_item].name); - else - rt_snprintf(new_path, sizeof(new_path), "%s%s",view->current_directory, - view->items[view->current_item].name); - } - rtgui_filelist_view_set_directory(view, new_path); - } - else - { - if (RTGUI_VIEW(view)->modal_show == RT_TRUE) - { - rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK); - } - } - return RT_FALSE; + rtgui_filelist_view_onenturn(view); + return RT_TRUE; default: break; @@ -720,10 +824,14 @@ __return: rtgui_widget_update(RTGUI_WIDGET(view)); } -void rtgui_filelist_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len) +void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len) { RT_ASSERT(view != RT_NULL); - rt_sprintf(path, "%s%c%s", view->current_directory, PATH_SEPARATOR, - view->items[view->current_item].name); + if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR) + rt_snprintf(path, len, "%s%c%s",view->current_directory, PATH_SEPARATOR, + view->items[view->current_item].name); + else + rt_snprintf(path, len, "%s%s",view->current_directory, + view->items[view->current_item].name); } diff --git a/components/rtgui/widgets/list_view.c b/components/rtgui/widgets/list_view.c index b638518d08..2a9f697c27 100644 --- a/components/rtgui/widgets/list_view.c +++ b/components/rtgui/widgets/list_view.c @@ -28,6 +28,7 @@ static void _rtgui_list_view_constructor(struct rtgui_list_view *view) RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + view->flag = RTGUI_LIST_VIEW_LIST; view->current_item = 0; view->items_count = 0; view->page_items = 0; @@ -49,18 +50,149 @@ rtgui_type_t *rtgui_list_view_type_get(void) return list_view_type; } -void rtgui_list_view_ondraw(struct rtgui_list_view* view) +static void rtgui_list_view_onicondraw(struct rtgui_list_view* view, struct rtgui_dc *dc) { - struct rtgui_rect rect, item_rect; + struct rtgui_rect rect, item_rect, drawing_rect; + rt_ubase_t c, r, item_index; /* col and row index */ + rt_ubase_t item_width, item_height; + rtgui_image_t* image; + + if (view->items_count == 0) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + item_index = (view->current_item / view->page_items) * view->page_items; + + item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; + item_height = (rtgui_rect_height(rect) - 4)/view->row_items; + image = view->items[0].image; + + for (r = 0; r < view->row_items; r ++) + { + for (c = 0; c < view->col_items; c ++) + { + if (item_index < view->items_count) + { + item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; + item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; + item_rect.x2 = item_rect.x1 + item_width; + item_rect.y2 = item_rect.y1 + item_height; + + if (item_index == view->current_item) + { + rtgui_theme_draw_selected(dc, &item_rect); + } + + drawing_rect.x1 = drawing_rect.y1 = 0; + drawing_rect.x2 = image->w; + drawing_rect.y2 = image->h; + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + drawing_rect.y1 += 3; drawing_rect.y2 += 3; + rtgui_image_blit(view->items[item_index].image, dc, &drawing_rect); + + item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; + item_rect.x1 += 3; item_rect.x2 -=3; + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[item_index].name, + &drawing_rect); + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_dc_draw_text(dc, view->items[item_index].name, &drawing_rect); + + item_index ++; + } + else break; + } + } +} + +static void rtgui_list_view_update_icon(struct rtgui_list_view* view, rt_uint16_t old_item) +{ + struct rtgui_rect rect, item_rect, drawing_rect; + rt_ubase_t c, r; /* col and row index */ + rt_ubase_t item_width, item_height; + rtgui_image_t* image; struct rtgui_dc* dc; - rt_uint16_t page_index, index; - const struct rtgui_list_item* item; + + if ((view->items_count == 0) || + (old_item == view->current_item)) + return; + + if (old_item/view->page_items != view->current_item/view->page_items) + { + /* it's not a same page, update all */ + rtgui_widget_update(RTGUI_WIDGET(view)); + return; + } dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); if (dc == RT_NULL) return; rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); - rtgui_dc_fill_rect(dc, &rect); + + item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; + item_height = (rtgui_rect_height(rect) - 4)/view->row_items; + image = view->items[0].image; + + /* update old item */ + r = (old_item % view->page_items)/ view->col_items; + c = (old_item % view->page_items)% view->col_items; + item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; + item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; + item_rect.x2 = item_rect.x1 + item_width; + item_rect.y2 = item_rect.y1 + item_height; + rtgui_dc_fill_rect(dc, &item_rect); + + /* draw image */ + drawing_rect.x1 = drawing_rect.y1 = 0; + drawing_rect.x2 = image->w; + drawing_rect.y2 = image->h; + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + drawing_rect.y1 += 3; drawing_rect.y2 += 3; + rtgui_image_blit(view->items[old_item].image, dc, &drawing_rect); + + /* draw text */ + item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; + item_rect.x1 += 3; item_rect.x2 -=3; + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[old_item].name, + &drawing_rect); + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_dc_draw_text(dc, view->items[old_item].name, &drawing_rect); + + /* update new item as selected */ + r = (view->current_item % view->page_items) / view->col_items; + c = (view->current_item % view->page_items) % view->col_items; + item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; + item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; + item_rect.x2 = item_rect.x1 + item_width; + item_rect.y2 = item_rect.y1 + item_height; + rtgui_theme_draw_selected(dc, &item_rect); + + /* draw image */ + drawing_rect.x1 = 0; + drawing_rect.y1 = 3; + drawing_rect.x2 = image->w; + drawing_rect.y2 = 3 + image->h; + + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_image_blit(view->items[view->current_item].image, dc, &drawing_rect); + + /* draw text */ + item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; + item_rect.x1 += 3; item_rect.x2 -=3; + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), + view->items[view->current_item].name, + &drawing_rect); + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_dc_draw_text(dc, view->items[view->current_item].name, &drawing_rect); + + rtgui_dc_end_drawing(dc); +} + +static void rtgui_list_view_onlistdraw(struct rtgui_list_view* view, struct rtgui_dc *dc) +{ + rt_ubase_t index, page_index; + rtgui_rect_t rect, item_rect, image_rect; + const struct rtgui_list_item* item; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); /* get item base rect */ item_rect = rect; @@ -83,24 +215,29 @@ void rtgui_list_view_ondraw(struct rtgui_list_view* view) if (item->image != RT_NULL) { - rtgui_image_blit(item->image, dc, &item_rect); + /* blit on center */ + image_rect.x1 = 0; image_rect.y1 = 0; + image_rect.x2 = item->image->w; + image_rect.y2 = item->image->h; + + 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 */ + /* draw text */ rtgui_dc_draw_text(dc, item->name, &item_rect); - if (item->image != RT_NULL) - item_rect.x1 -= (item->image->w + 2); + if (item->image != RT_NULL) + item_rect.x1 -= (item->image->w + 2); item_rect.x1 -= LIST_MARGIN; - /* move to next item position */ + /* move to next item position */ item_rect.y1 += (rtgui_theme_get_selected_height() + 2); item_rect.y2 += (rtgui_theme_get_selected_height() + 2); } - rtgui_dc_end_drawing(dc); } -void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t old_item) +void rtgui_list_view_update_list(struct rtgui_list_view* view, rt_uint16_t old_item) { struct rtgui_dc* dc; const struct rtgui_list_item* item; @@ -118,13 +255,11 @@ void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t ol rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); - item_rect = rect; - /* get old item's rect */ - item_rect.y1 += 2; + /* get old item's rect and draw old item */ + item_rect.x1 = rect.x1; item_rect.x2 = rect.x2; + item_rect.y1 = rect.y1 + 2; item_rect.y1 += (old_item % view->page_items) * (2 + rtgui_theme_get_selected_height()); item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); - - /* draw old item */ rtgui_dc_fill_rect(dc, &item_rect); item_rect.x1 += LIST_MARGIN; @@ -132,7 +267,15 @@ void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t ol item = &(view->items[old_item]); if (item->image != RT_NULL) { - rtgui_image_blit(item->image, dc, &item_rect); + struct rtgui_rect image_rect; + + /* blit on center */ + image_rect.x1 = 0; image_rect.y1 = 0; + image_rect.x2 = item->image->w; + image_rect.y2 = item->image->h; + + 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); @@ -152,14 +295,135 @@ void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t ol item = &(view->items[view->current_item]); if (item->image != RT_NULL) { - rtgui_image_blit(item->image, dc, &item_rect); - item_rect.x1 += (item->image->w + 2); + struct rtgui_rect image_rect; + + /* blit on center */ + image_rect.x1 = 0; image_rect.y1 = 0; + image_rect.x2 = item->image->w; + image_rect.y2 = item->image->h; + + 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); rtgui_dc_end_drawing(dc); } +void rtgui_list_view_ondraw(struct rtgui_list_view* view) +{ + struct rtgui_rect rect; + struct rtgui_dc* dc; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + rtgui_dc_fill_rect(dc, &rect); + + switch (view->flag) + { + case RTGUI_LIST_VIEW_LIST: + rtgui_list_view_onlistdraw(view, dc); + break; + + case RTGUI_LIST_VIEW_ICON: + rtgui_list_view_onicondraw(view, dc); + break; + } + + rtgui_dc_end_drawing(dc); +} + +static rt_bool_t rtgui_list_view_onmouse(struct rtgui_list_view* view, struct rtgui_event_mouse* emouse) +{ + rtgui_rect_t rect; + + /* calculate selected item */ + + /* get physical extent information */ + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + rtgui_widget_rect_to_device(RTGUI_WIDGET(view), &rect); + + if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) + { + rt_uint16_t index; + rt_uint16_t old_item; + + /* get old item */ + old_item = view->current_item; + + switch (view->flag) + { + case RTGUI_LIST_VIEW_LIST: + index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); + + if ((index < view->items_count) && (index < view->page_items)) + { + /* set selected item */ + view->current_item = (view->current_item/view->page_items) * view->page_items + index; + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + /* down event */ + rtgui_list_view_update_list(view, old_item); + } + else + { + /* up event */ + if (view->items[view->current_item].action != RT_NULL) + { + view->items[view->current_item].action(view->items[view->current_item].parameter); + } + } + } + break; + + case RTGUI_LIST_VIEW_ICON: + { + rt_uint16_t x, y; + rt_uint16_t item_height, item_width; + rt_ubase_t current_page; + + item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; + item_height = (rtgui_rect_height(rect) - 4)/view->row_items; + x = emouse->x - rect.x1; + y = emouse->y - rect.y1; + + index = (y / item_height * view->col_items) + x / item_width; + current_page = view->current_item / view->page_items; + + if ((index + (current_page * view->page_items) < view->items_count)) + { + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + view->current_item = index + (current_page * view->page_items); + + /* down event */ + rtgui_list_view_update_icon(view, old_item); + } + else + { + /* up event */ + if (view->items[view->current_item].action != RT_NULL) + { + view->items[view->current_item].action(view->items[view->current_item].parameter); + } + } + } + } + break; + + case RTGUI_LIST_VIEW_REPORT: + break; + } + + return RT_TRUE; + } + + return RT_FALSE; +} + rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) { struct rtgui_list_view* view = RT_NULL; @@ -184,35 +448,11 @@ rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgu case RTGUI_EVENT_MOUSE_BUTTON: { - rtgui_rect_t rect; struct rtgui_event_mouse* emouse; emouse = (struct rtgui_event_mouse*)event; - - /* calculate selected item */ - - /* get physical extent information */ - rtgui_widget_get_rect(widget, &rect); - rtgui_widget_rect_to_device(widget, &rect); - - if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) - { - rt_uint16_t index; - index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); - - if ((index < view->items_count) && (index < view->page_items)) - { - rt_uint16_t old_item; - - old_item = view->current_item; - - /* set selected item */ - view->current_item = (view->current_item/view->page_items) * view->page_items + index; - rtgui_list_view_update_current(view, old_item); - } - } + return rtgui_list_view_onmouse(view, emouse); } - break; case RTGUI_EVENT_KBD: { @@ -225,27 +465,73 @@ rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgu switch (ekbd->key) { case RTGUIK_LEFT: - if (view->current_item - view->page_items >= 0) - view->current_item -= view->page_items; - rtgui_list_view_update_current(view, old_item); + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item - view->page_items >= 0) + view->current_item -= view->page_items; + + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item > 0) + view->current_item --; + rtgui_list_view_update_icon(view, old_item); + } return RT_FALSE; case RTGUIK_UP: - if (view->current_item > 0) - view->current_item --; - rtgui_list_view_update_current(view, old_item); + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item > 0) + view->current_item --; + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item >= view->col_items) + view->current_item -= view->col_items; + else + view->current_item = 0; + + rtgui_list_view_update_icon(view, old_item); + } return RT_FALSE; case RTGUIK_RIGHT: - if (view->current_item + view->page_items < view->items_count - 1) - view->current_item += view->page_items; - rtgui_list_view_update_current(view, old_item); + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item + view->page_items < view->items_count - 1) + view->current_item += view->page_items; + + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item < view->items_count - 1) + view->current_item ++; + + rtgui_list_view_update_icon(view, old_item); + } return RT_FALSE; case RTGUIK_DOWN: - if (view->current_item < view->items_count - 1) - view->current_item ++; - rtgui_list_view_update_current(view, old_item); + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item < view->items_count - 1) + view->current_item ++; + + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item + view->col_items <= (view->items_count - 1)) + view->current_item += view->col_items; + else + view->current_item = view->items_count - 1; + + rtgui_list_view_update_icon(view, old_item); + } return RT_FALSE; case RTGUIK_RETURN: @@ -267,7 +553,35 @@ rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgu return rtgui_view_event_handler(widget, event); } -rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count, rtgui_rect_t *rect) +static void rtgui_list_view_calc(struct rtgui_list_view* view) +{ + /* get image of first item*/ + rtgui_image_t *image; + rtgui_rect_t rect; + rt_ubase_t text_width, text_height; + rt_ubase_t item_width, item_height; + + if (view->items_count == 0) return; + + image = view->items[0].image; + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "HHHHHH", &rect); + + text_height = rtgui_rect_height(rect); + text_width = rtgui_rect_width(rect); + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + + item_width = (image->w + LIST_MARGIN); + if (item_width < (text_width + LIST_MARGIN)) item_width = text_width + LIST_MARGIN; + item_height = image->h + 3 + text_height + LIST_MARGIN; + + view->row_items = (rtgui_rect_height(rect) - 2 * LIST_MARGIN) / item_height; + view->col_items = (rtgui_rect_width(rect) - 2 * LIST_MARGIN) / item_width; + view->page_items = view->row_items * view->col_items; +} + +rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count, + rtgui_rect_t *rect, rt_uint16_t flag) { struct rtgui_list_view* view = RT_NULL; @@ -277,7 +591,15 @@ rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, r view->items = items; view->items_count = count; - view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height()); + view->flag = flag; + rtgui_widget_set_rect(RTGUI_WIDGET(view), rect); + + if (flag == RTGUI_LIST_VIEW_LIST) + view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height()); + else if ((flag == RTGUI_LIST_VIEW_ICON) && (count > 0)) + { + rtgui_list_view_calc(view); + } } return view; diff --git a/components/rtgui/widgets/listbox.c b/components/rtgui/widgets/listbox.c index 1925d794a8..62e550f958 100644 --- a/components/rtgui/widgets/listbox.c +++ b/components/rtgui/widgets/listbox.c @@ -201,7 +201,7 @@ rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_ rtgui_widget_get_rect(widget, &rect); rtgui_widget_rect_to_device(widget, &rect); - if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) + if ((rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) && (box->items_count > 0)) { rt_uint16_t index; index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); @@ -249,13 +249,14 @@ rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_ } } } + + return RT_TRUE; } - break; case RTGUI_EVENT_KBD: { struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; - if (ekbd->type == RTGUI_KEYDOWN) + if ((ekbd->type == RTGUI_KEYDOWN) && (box->items_count > 0)) { rt_uint16_t old_item; @@ -334,3 +335,18 @@ void rtgui_listbox_set_onitem(rtgui_listbox_t* box, rtgui_onitem_func_t func) box->on_item = func; } + +void rtgui_listbox_set_items(rtgui_listbox_t* box, struct rtgui_listbox_item* items, rt_uint16_t count) +{ + rtgui_rect_t rect; + + box->items = items; + box->items_count = count; + box->current_item = 0; + + rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect); + box->page_items = rtgui_rect_height(rect) / (2 + rtgui_theme_get_selected_height()); + + rtgui_widget_update(RTGUI_WIDGET(box)); +} + diff --git a/components/rtgui/widgets/window.c b/components/rtgui/widgets/window.c index b11690fbae..dca8fb668f 100644 --- a/components/rtgui/widgets/window.c +++ b/components/rtgui/widgets/window.c @@ -465,7 +465,7 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even break; case RTGUI_EVENT_MOUSE_BUTTON: - if (win->flag & RTGUI_WORKBENCH_FLAG_MODAL_MODE) + if (win->flag & RTGUI_WIN_STYLE_MODAL) { if (win->modal_widget != RT_NULL) return win->modal_widget->event_handler(win->modal_widget, event); @@ -500,7 +500,7 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even break; case RTGUI_EVENT_KBD: - if (win->flag & RTGUI_WORKBENCH_FLAG_MODAL_MODE) + if (win->flag & RTGUI_WIN_STYLE_MODAL) { if (win->modal_widget != RT_NULL) return win->modal_widget->event_handler(win->modal_widget, event);