|
|
Beginners guide to using the List WidgetWhat is the List WidgetSince you're reading this, you're probably in the need of some nice, efficient, generic, well tested piece of code to help you show a list of something in your contribution to RockBox. Well, that piece of code is usually referred to as the List Widget in the IRC channel and it can be found in %ROCKBOX_HOME%/apps/gui/list.c. I'm writing this guide because I hope I can make it simpler to use by new contributors to RockBox. Even though lists can be used in several, well known situations like file browsing, menus and the music database, the highly generic way lists are implemented in this case expands those situations to even implement a text viewer, a file/folder property viewer and many other things to come.A brief discussion of the architectureLet's start off by pointing out that I didn't write the List Widget, as a matter of fact, I started using it yesterday and I (sadly) realized this document didn't already exist. So discussing the architecture may well be out of my jurisdiction. However, I do know this brief explanation can clarify some things to new contributors and will hopefully be improved by other more experienced users. When someone hears about something that handles lists, at first thought he can expect the code to be a generic data structure that will hold all the necessary information in some kind of data structure (i.e.: a linked list). However, the List Widget is not designed to store data, but either to display data in the form of a list and handle user interaction like scrolling and selecting items within the list. But if the List Widget will not store the data, where/how will the data be stored? Well, that's the great part. It's entirely up to you. It can well be a linked list, an array, a file, you name it. All that is needed for the list to work is that you're able to reference the appropriate item in the list by it's index. Ok, but if the List doesn't have the data, how will it know what to show in the list? Certainly, the list doesn't hold the data that is listed, so it need a link to the data. That link is implemented as a function pointer. For the widget to show the labels of the items in the list, you implement a function that will provide the label when the index of the item to be shown is handed over to it (as well as a couple other parameter I'll discuss later). Besides allowing to easily list items, the widget has several other useful features including:
How to use the widgetEnough talking, let's get down to business and start coding. As an example, I will assume a list of names is stored in a linked list in a structure like this:struct names_list { char first_name[10]; char last_name[10]; struct names_list *next; }Since this topic is not about linked lists, I'll skip the part where the list is filled with data. All you need to know is that we have a: struct names_list *people;that points to the first item in the list and that we can reach the next item in the list by invoking: people->next;as I said in the architecture, how the data is stored is entirely up to you. Declaration of the listIn order to use the list, you obviously need to #include something. Luckily, plugin.h has everything we need, from data structures to function pointers. So we should start by:#include "plugin.h"but you probably already included that one. After that, we declare the list itself: struct gui_synclist gui_people; Initialization of the list widgetAs I mentioned before, the list doesn't hold the data itself but a pointer to a function. Of course how you create the label of an item can vary a lot, but your function should look similar to this:char * get_person_label(int selected_item, void *data, char *buffer, size_t buffer_len){ int i; struct names_list *temp_node = (struct names_list *)data; for (i=0;i<selected_item && temp_node != NULL;i++){ temp_node = temp_node->next; } if (temp_node == NULL){ return NULL; } rb->snprintf(buffer, buffer_len,"%s, %s", temp_node->last_name, temp_node->first_name); return buffer; }What can be seen here is:
rb->gui_synclist_init(&gui_people, &get_person_label, people, false, 1);What's all that????? relax, it's not that much:
Set some propertiesOk, the list is initialized, but it may need some more property-setting before it looks and behaves the way we want to. I'll set some properties all at once and elaborate later:rb->gui_synclist_set_title(&gui_people, "Contacts", NOICON); rb->gui_synclist_set_icon_callback(&gui_people, &get_person_icon); rb->gui_synclist_set_nb_items(&gui_people, people_count); rb->gui_synclist_limit_scroll(&gui_people, true); rb->gui_synclist_select_item(&gui_people, 0);Ok, what do you have here?
Handling interaction with the listLast but not least, we have to draw the list in the screen and handle user interaction. Let's see a piece of code again and explain it line by line:int curr_selection = 0; /* not strictly needed */ int button; while (true) { rb->gui_syncstatusbar_draw(rb->statusbars, true); /* draw the statusbar, shuold be done often */ button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); /* user input */ if (rb->gui_synclist_do_button(&gui_people, &button, LIST_WRAP_UNLESS_HELD)) { /* automatic handling of user input. _UNLESS_HELD can be _ON or _OFF also */ continue; } switch (button) { /* process the user input */ case ACTION_STD_OK: return rb->gui_synclist_get_sel_pos(&gui_people);; break; case ACTION_STD_CANCEL: return NULL; break; } }We need both the list widget and ourselves to handle user button clicks so everything works fine. To allow this, we're expected to get user actions and hand them over to the widget. After that, we can further handle the actions to complete the functionality.
Further readingAll the functions of the widget are well documented in %ROCKBOX_HOME%/apps/gui/list.h, while I tried to make this a complete guide, there are some other functions of the list like adding/removing items I didn't cover. Also, I didn't write much about icons but you can find several examples in the plugins and the core itself. -- MauricioPeccorini - 29 May 2007 commented the code to help new users, and fixed it up a bit -- JonathanGordon - 30 May 2007r7 - 02 Apr 2021 - 20:46:07 - UnknownUser
Copyright © by the contributing authors.
|