Using Edje Text Classes
This tutorial demonstrates how you can change the text of 2 or more parts using Edje text classes.
If a part is assigned with a text class, setting font attributes to this class updates all those parts with the new font attributes. Setting the values to a text class affects all parts in that text class at process level, while at the object level, it only affects the parts inside a specified object.
Creating the Basic Application
The example application has 2 screen with different UIs. The screens demonstrate different text class APIs. The screen contains a genlist with 2 items set into a naviframe. Clicking an item opens displays a screen. Pressing the hardware Back button displays the main screen with the genlist.
- Create the basic application:
static void win_back_cb(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; elm_naviframe_item_pop(ad->navifr); }
-
Get the path to the EDC file that contains the main layout and the Edje object to load:
static void app_get_resource(const char *edj_file_in, char *edj_path_out, int edj_path_max) { char *res_path = app_get_resource_path(); if (res_path) { snprintf(edj_path_out, edj_path_max, "%s%s", res_path, edj_file_in); free(res_path); } }
Create a window and register an event callback that calls the win_back_cb() function after pressing the Back button on the device:
static void create_base_gui(appdata_s *ad) { Elm_Object_Item *eoi = NULL; // Window ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE); elm_win_conformant_set(ad->win, EINA_TRUE); elm_win_autodel_set(ad->win, EINA_TRUE); if (elm_win_wm_rotation_supported_get(ad->win)) { int rots[4] = {0, 90, 180, 270}; elm_win_wm_rotation_available_rotations_set(ad->win, (const int *)(&rots), 4); } eext_object_event_callback_add(ad->win, EEXT_CALLBACK_BACK, win_back_cb, ad); }
-
Add a conformant that contains the naviframe and genlist. Add item selection callbacks for the genlist items to show different screens:
static char * _genlist_item_text_get(void *data, Evas_Object *obj, const char *part) { Eina_Stringshare *text_class = (Eina_Stringshare *)data; if (strcmp(part, "elm.text") == 0) return strdup(text_class); else return NULL; } static void create_base_gui(appdata_s *ad) { // Conformant ad->conform = elm_conformant_add(ad->win); elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW); elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE); evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, ad->conform); evas_object_show(ad->conform); // Naviframe ad->navifr = elm_naviframe_add(ad->win); elm_object_content_set(ad->conform, ad->navifr); eext_object_event_callback_add(ad->navifr, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, ad); // Genlist ad->itc = elm_genlist_item_class_new(); ad->itc->func.text_get =_genlist_item_text_get; ad->genlist = elm_genlist_add(ad->win); evas_object_size_hint_weight_set(ad->genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); eoi = elm_genlist_item_append(ad->genlist, ad->itc, eina_stringshare_add("Text Class List"), NULL, ELM_GENLIST_ITEM_NONE, NULL, ad); eoi = elm_genlist_item_append(ad->genlist, ad->itc, eina_stringshare_add("Object Text Class API"), NULL, ELM_GENLIST_ITEM_NONE, NULL, ad); elm_naviframe_item_simple_push(ad->navifr, ad->genlist); // Show the window evas_object_show(ad->win); }
The following figure shows the result.
Figure: Main screen
Getting, Deleting, and Displaying Text Classes
The first screen of the application shows an example of the edje_text_class_del(), edje_text_class_list(), and edje_text_class_get() functions.
The following code implements the layout:
group { name: "class_list_application"; parts { part { name: "text_view"; type: TEXT; description { state: "default" 0.0; visible: 1; color: 0 0 0 255; align: 0.5 0.0; text { text: "text part number 3"; font: "Sans"; min: 1 1; max: 1 1; size: 20; } } } part { name: "edje.swallow.list"; type: SWALLOW; description { state: "default" 0.0; align: 0.5 0.0; color: 0 0 0 255; rel1 { relative: 0.0 1.0; to_y: "text_view"; } } } } }
Figure: First screen EDC layout
The first part (text_view) shows the properties of the selected text class. Clicking a text class in the genlist shows its properties, such as font, size, and name in the text part.
-
Add the base genlist:
ad->genlist = elm_genlist_add(ad->win); evas_object_size_hint_weight_set(ad->genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); eoi = elm_genlist_item_append(ad->genlist, ad->itc, eina_stringshare_add("Text Class List"), NULL, ELM_GENLIST_ITEM_NONE, _create_class_list_gui, ad); eoi = elm_genlist_item_append(ad->genlist, ad->itc, eina_stringshare_add("Object Text Class API"), NULL, ELM_GENLIST_ITEM_NONE, NULL, ad); elm_naviframe_item_simple_push(ad->navifr, ad->genlist);
-
Load the layout:
static void _create_class_list_gui(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; // Get application's data char edj_path[PATH_MAX] = {0, }; // path to edc file Eina_List *l; // Used later const char *str; // Used later Elm_Object_Item *eoi = NULL; // Used later app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX); // Main layout ad->gui1_layout = elm_layout_add(ad->win); evas_object_size_hint_weight_set(ad->gui1_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_file_set(ad->gui1_layout, edj_path, "class_list_application"); }
-
Get a list of all text classes loaded into the system.In the following example, the Eina_List list is a field in application data.
ad->list = edje_text_class_list();
-
Create the genlist:
// Genlist ad->itc_text_classes = elm_genlist_item_class_new(); ad->itc_text_classes->func.text_get =_genlist_item_text_get; ad->genlist_text_classes = elm_genlist_add(ad->win); evas_object_size_hint_weight_set(ad->genlist_text_classes, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-
Go through the text class list and insert each text class to the genlist. Set the genlist into the main layout of the current screen and show it in the naviframe:
EINA_LIST_FOREACH(ad->list, l, str) { eoi = elm_genlist_item_append(ad->genlist_text_classes, ad->itc_text_classes, str, NULL, ELM_GENLIST_ITEM_NONE, NULL, ad); elm_object_item_data_set(eoi, (void *)str); } elm_object_part_content_set(ad->gui1_layout, "edje.swallow.list", ad->genlist_text_classes); evas_object_show(ad->genlist_text_classes); elm_naviframe_item_simple_push(ad->navifr, ad->gui1_layout);
Clicking Text Class List displays the screen with a genlist of text classes.
Figure: Text class list
-
The edje_text_class_del() function deletes a text class (in the following example, T094):
// Main layout ad->gui1_layout = elm_layout_add(ad->win); evas_object_size_hint_weight_set(ad->gui1_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_file_set(ad->gui1_layout, edj_path, "class_list_application"); evas_object_show(ad->gui1_layout); // Get the collection list app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX); edje_text_class_del("T094"); ad->list = edje_text_class_list(); // Genlist ad->itc_text_classes = elm_genlist_item_class_new(); ad->itc_text_classes->func.text_get =_genlist_item_text_get;
Figure: Text class list after deleting a class
-
Every text class contains specific information, such as the font name, font size, and text class name. To show the properties when the text class name is clicked, create a callback that uses the edje_text_class_get() function:
static void _genlist_clicked(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; char text_class[PATH_MAX] = {0, }; Elm_Object_Item *eoi = NULL; const char *str; char *font; Evas_Font_Size size; eoi = elm_genlist_selected_item_get(obj); str = elm_object_item_data_get(eoi); edje_text_class_get(str, &font, &size); snprintf(text_class, PATH_MAX, "%s font{%s} size{%d}", str, font, size); elm_object_part_text_set(ad->gui1_layout, "text_view", text_class); }
-
Register the added callback function in the genlist:
EINA_LIST_FOREACH(ad->list, l, str) { eoi = elm_genlist_item_append(ad->genlist_text_classes, ad->itc_text_classes, str, NULL, ELM_GENLIST_ITEM_NONE, _genlist_clicked, ad); elm_object_item_data_set(eoi, (void *)str); } elm_object_part_content_set(ad->gui1_layout, "edje.swallow.list", ad->genlist_text_classes); evas_object_show(ad->genlist_text_classes); elm_naviframe_item_simple_push(ad->navifr, ad->gui1_layout);
Figure: Displaying text class properties
Application Layout
The second screen contains 2 Edje object with text parts containing the custom_text_class text class. When a text class is modified, all text parts assigned to it are changed as well.
The following example shows a simple Edje object layout:
group { name: "edje_example"; parts { part { name: "text_example"; type: TEXT; description { state: "default" 0.0; visible: 1; color: 0 0 0 255; text { text: "text part number 3"; font: "Sans"; size: 10; text_class: "custom_text_class"; } } } } }
-
After loading the Edje objects, add a spinner for changing the font size.
Add 2 buttons for changing the text class of a specific object or setting the font size of the custom_text_class text class. The Set1 button sets a new size for the text class of the first Edje object and the Set2 button for the second object, respectively.
The Get1 and Get2 buttons get the text class properties and display them on the screen.
The Global button changes the text class globally, causing all Edje object parts to be changed in case they contain the custom_text_class text class.
group { name: "object_text_class_application"; parts { part { name: "bg"; type: RECT; description { state: "default" 0.0; } } part { name: "edje.swallow.group1"; type: SWALLOW; description { state: "default" 0.0; rel1.relative: 0.02 0.1; rel2.relative: 0.3 0.2; } } part { name: "edje.swallow.group2"; type: SWALLOW; description { state: "default" 0.0; rel1.relative: 0.5 0.1; rel2.relative: 0.77 0.2; } } part { name: "edje.swallow.spinner"; type: SWALLOW; description { state: "default" 0.0; rel1.relative: 0.2 0.2; rel2.relative: 0.9 0.35; } } part { name: "edje.swallow.buttons"; type: SWALLOW; description { state: "default" 0.0; rel1.relative: 0.0 0.9; rel2.relative: 1.0 1.0; } } part { name: "text_spin"; type: TEXT; scale: 1; description { state: "default" 0.0; visible: 1; color: 0 0 0 255; rel1.relative: 0.0 0.2; rel2.relative: 0.2 0.35; text { text: "Font Size"; font: "Sans"; align: 0.0 0.5; size: 13; } } } }
-
Create a view for the new screen:
static void _create_text_class_gui(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; char edj_path[PATH_MAX] = {0, }; app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX); // Main Layout ad->gui2_layout = elm_layout_add(ad->win); evas_object_size_hint_weight_set(ad->gui2_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_file_set(ad->gui2_layout, edj_path, "object_text_class_application"); evas_object_show(ad->gui2_layout); // Add group1 ad->edje_object_1 = edje_object_add(evas_object_evas_get(ad->win)); evas_object_size_hint_weight_set(ad->edje_object_1, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); edje_object_file_set(ad->edje_object_1, edj_path, "edje_example"); // Check the object loading error if (edje_object_load_error_get(ad->edje_object_1) != EDJE_LOAD_ERROR_NONE) { evas_object_del(ad->edje_object_1); return; } evas_object_show(ad->edje_object_1); elm_object_part_content_set(ad->gui2_layout, "edje.swallow.group1", ad->edje_object_1); // Addgroup2 ad->edje_object_2 = edje_object_add(evas_object_evas_get(ad->win)); evas_object_size_hint_weight_set(ad->edje_object_2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); edje_object_file_set(ad->edje_object_2, edj_path, "edje_example"); // Check object loading errors if (edje_object_load_error_get(ad->edje_object_2) != EDJE_LOAD_ERROR_NONE) { evas_object_del(ad->edje_object_2); return; } evas_object_show(ad->edje_object_2); elm_object_part_content_set(ad->gui2_layout, "edje.swallow.group2", ad->edje_object_2); // Add spinner ad->spinner = elm_spinner_add(ad->win); evas_object_size_hint_weight_set(ad->spinner, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->spinner, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_spinner_min_max_set(ad->spinner, 1, 64); elm_spinner_step_set(ad->spinner, 1); evas_object_show(ad->spinner); elm_spinner_value_set(ad->spinner, 10); elm_object_part_content_set(ad->gui2_layout, "edje.swallow.spinner", ad->spinner); elm_naviframe_item_simple_push(ad->navifr, ad->gui2_layout); }
Figure: Second application screen
Setting the Text Class for All Edje Objects
To set the text class globally, use the edje_test_class_set() function:
-
Add a box and pack the buttons into it. Add the Global button and register a callback for clicking:
static void _create_text_class_gui(void *data, Evas_Object *obj, void *event_info) { Evas_Object *box, *button; // Add the box box = elm_box_add(ad->gui2_layout); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, 0.0); elm_box_horizontal_set(box, EINA_TRUE); evas_object_show(box); button = elm_button_add(ad->gui2_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "Global"); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_text_class_set, ad); elm_box_pack_end(box, button); elm_object_part_content_set(ad->gui2_layout, "edje.swallow.buttons", box); elm_naviframe_item_simple_push(ad->navifr, ad->gui2_layout); }
-
The callback contains functions for setting the text class globally:
static void _edje_text_class_set(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; edje_text_class_set("custom_text_class", "Sans", elm_spinner_value_get(ad->spinner)); }
Clicking the Global button recalculates all text parts in every Edje object that contains the custom_text_class text class and changes their size.
Figure: Changing the text class globally
Setting the Text Class of a Specific Object
To set the text class of a specific Edje object, use the edje_object_test_class_set() function.
-
Add 2 more buttons, Set1 and Set2.
The first button sets the text class of the first Edje object on the left, and the second sets the text class of the other object, respectively.
static void _create_text_class_gui(void *data, Evas_Object *obj, void *event_info) { button = elm_button_add(ad->gui2_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "Set1"); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_object_text_class_set_1, ad); elm_box_pack_end(box, button); button = elm_button_add(ad->gui2_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "Set2"); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_object_text_class_set_2, ad); elm_box_pack_end(box, button); }
-
Add callbacks:
static void _edje_object_text_class_set_1(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; edje_object_text_class_set(ad->edje_object_1, "custom_text_class", "Sans", elm_spinner_value_get(ad->spinner)); } static void _edje_object_text_class_set_2(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; edje_object_text_class_set(ad->edje_object_2, "custom_text_class", "Sans", elm_spinner_value_get(ad->spinner)); }
-
Test the functionality:
- Set the size of the left object to 16.
- Set the size of the right object to 44.
- Set the size of the right object to 22.
Getting the Text Class of an Object
To get the text class of a specific Edje object, use the edje_object_test_class_get() function.
-
Add 2 more buttons, Get1 and Get2. The first gets the text class of the first Edje object on the left and sets into that object result, and the second gets the text class of the other object, respectively.
static void _create_text_class_gui(void *data, Evas_Object *obj, void *event_info) { button = elm_button_add(ad->gui2_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "Get1"); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_object_text_class_get_1, ad); elm_box_pack_end(box, button); button = elm_button_add(ad->gui2_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "Get2"); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_object_text_class_get_2, ad); elm_box_pack_end(box, button); }
-
Add callbacks:
static void _edje_object_text_class_get_1(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; char *font; Evas_Font_Size size; char text_class[PATH_MAX] = {0, }; edje_object_text_class_get(ad->edje_object_1, "custom_text_class", &font, &size); snprintf(text_class, PATH_MAX, "font{%s} size{%d}", font, size); edje_object_part_text_set(ad->edje_object_1, "text_example", text_class); } static void _edje_object_text_class_get_2(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; char *font; Evas_Font_Size size; char text_class[PATH_MAX] = {0, }; edje_object_text_class_get(ad->edje_object_2, "custom_text_class", &font, &size); snprintf(text_class, PATH_MAX, "font{%s} size{%d}", font, size); edje_object_part_text_set(ad->edje_object_2, "text_example", text_class); }
The following figure shows the result.
Figure: Displaying text class changes
Changing the custom_text_class for the first object changed its font size to 16 size, while changing the custom_text_class for the second object changes its font size to 22.