The (Circle) Settings sample application demonstrates how to implement a circular view with the elementary UI components and EFL Extension circular UI components.
The sample uses UI components, such as elm_conformant and elm_naviframe for view management, elm_layout for UI component management inside the view, and elm_genlist for the content inside the main view. elm_genlist has three items: volume, brightness and information. When the item is clicked, its content is shown. To display a circular genlist component, the genlist component uses a circular genlist component supported by the EFL Extension.
The following figure illustrates the main view of the (Circle) Settings sample application, its wireframe structure, and component tree.
Figure: (Circle) Settings main view
Implementation
Main View
The create_base_gui() function is responsible for creating the application layout. It starts by creating a window, then adds elm_conformant to it to add surface for the circular component visual effect renderer. The conformant contains a layout for elm_naviframe which is added to act as a view manager of the window.
static void create_base_gui(appdata_s *ad) { Evas_Object *conform = NULL; // Window ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE); 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); } evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL); // Conformant conform = elm_conformant_add(ad->win); evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, conform); evas_object_show(conform); // Naviframe ad->naviframe = elm_naviframe_add(conform); elm_object_content_set(conform, ad->naviframe); // Eext Circle Surface ad->circle_surface = eext_circle_surface_naviframe_add(ad->naviframe); // Main View create_list_view(ad); eext_object_event_callback_add(ad->naviframe, EEXT_CALLBACK_BACK, eext_naviframe_back_cb, NULL); eext_object_event_callback_add(ad->naviframe, EEXT_CALLBACK_MORE, eext_naviframe_more_cb, NULL); // Show the window after the base GUI is set up evas_object_show(ad->win); }
The main view is created using the create_list_view() function and it is added to the naviframe. In this function, the circular genlist is created for the circular UI which requires the genlist object to initialize itself. After that, three setting items are generated and appended to the circular genlist.
static void create_list_view(appdata_s *ad) { Evas_Object *genlist = NULL; Evas_Object *naviframe = ad->naviframe; Elm_Object_Item *nf_it = NULL; Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new(); Elm_Genlist_Item_Class *titc = elm_genlist_item_class_new(); Elm_Genlist_Item_Class *pitc = elm_genlist_item_class_new(); item_data *id = NULL; int index = 0; // Genlist genlist = elm_genlist_add(naviframe); elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS); evas_object_smart_callback_add(genlist, "selected", NULL, NULL); ad->circle_genlist = eext_circle_object_genlist_add(genlist, ad->circle_surface); eext_circle_object_genlist_scroller_policy_set(ad->circle_genlist, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); eext_rotary_object_event_activated_set(ad->circle_genlist, EINA_TRUE); // Genlist item style itc->item_style = "default"; itc->func.text_get = _gl_main_text_get; itc->func.del = _gl_del; // Genlist title item style titc->item_style = "title"; titc->func.text_get = _gl_title_text_get; titc->func.del = _gl_del; // Genlist padding item style pitc->item_style = "padding"; // Title item here elm_genlist_item_append(genlist, titc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, ad); // Main menu items here id = calloc(sizeof(item_data), 1); id->index = index++; id->item = elm_genlist_item_append(genlist, itc, id, NULL, ELM_GENLIST_ITEM_NONE, _setting_volume_cb, ad); id = calloc(sizeof(item_data), 1); id->index = index++; id->item = elm_genlist_item_append(genlist, itc, id, NULL, ELM_GENLIST_ITEM_NONE, _setting_brightness_cb, ad); id = calloc(sizeof(item_data), 1); id->index = index++; id->item = elm_genlist_item_append(genlist, itc, id, NULL, ELM_GENLIST_ITEM_NONE, _setting_information_cb, ad); // Padding item here elm_genlist_item_append(genlist, pitc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, ad); nf_it = elm_naviframe_item_push(naviframe, NULL, NULL, NULL, genlist, "empty"); elm_naviframe_item_pop_cb_set(nf_it, _naviframe_pop_cb, ad->win); }
Volume View
When the volume item is clicked, the volume view is shown in the main view. The following figure illustrates the volume view and its wireframe structure.
Figure: (Circle) Settings volume view
The _setting_volume_cb() callback function is called when the first item whose name is volume is clicked. In this function, a circular slider object is created by the eext_circle_object_slider_add() function. It needs the circular surface to render the circular slider on the surface. The eext_rotary_object_event_activated_set() function is called to receive the rotary event. After that, the _value_changed_cb() callback function is added to the circular slider to change the text as the circular slider value is changed.
static void _setting_volume_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { char edj_path[PATH_MAX] = {0,}; appdata_s *ad = data; Evas_Object *naviframe = ad->naviframe; Evas_Object *layout = NULL; Evas_Object *slider = NULL; Elm_Object_Item *nf_it = NULL; app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX); layout = elm_layout_add(naviframe); elm_layout_file_set(layout, edj_path, "slider_layout"); elm_object_part_text_set(layout, "elm.text.slider", "3.0"); evas_object_show(layout); slider = eext_circle_object_slider_add(layout, ad->circle_surface); eext_circle_object_value_min_max_set(slider, 0.0, 15.0); eext_circle_object_value_set(slider, 3.0); eext_rotary_object_event_activated_set(slider, EINA_TRUE); eext_circle_object_slider_step_set(slider, 0.5); evas_object_smart_callback_add(slider, "value,changed", _volume_changed_cb, layout); nf_it = elm_naviframe_item_push(naviframe, _("Slider"), NULL, NULL, layout, "empty"); elm_naviframe_item_pop_cb_set(nf_it, _setting_finished_cb, ad); }
The _volume_changed_cb() callback function is called when the volume value is changed. In this function, the layout text is changed using the eext_circle_object_value_get() function which gets the current value of the circular slider.
static void _volume_changed_cb(void *data, Evas_Object *obj, void *event_info) { char buf[PATH_MAX]; Evas_Object *layout = data; snprintf(buf, sizeof(buf), "%.1lf", eext_circle_object_value_get(obj)); printf("Slider value = %s\n", buf); elm_object_part_text_set(layout, "elm.text.slider", buf); }
Brightness View
When the brightness item is clicked, the brightness view is shown in the main view. The following figure illustrates the brightness view and its wireframe structure.
Figure: (Circle) Settings brightness view
The _setting_brightness_cb() callback function is called when the second item whose name is brightness is clicked. In this function, a circular slider object is created by the eext_circle_object_slider_add() function and 10 rectangles are created to display the circular slider value visually. Also, the _brightness_changed_cb() callback function is registered to change the value as the circular slider has changed.
static void _setting_brightness_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { char edj_path[PATH_MAX] = {0,}; appdata_s *ad = data; Evas_Object *naviframe = ad->naviframe; Evas_Object *layout = NULL; Evas_Object *slider = NULL; Evas_Object *box = NULL; Evas_Object *rect[10] = {NULL,}; Elm_Object_Item *nf_it = NULL; int i; app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX); layout = elm_layout_add(naviframe); elm_layout_file_set(layout, edj_path, "slider_layout"); evas_object_show(layout); box = elm_box_add(layout); elm_box_horizontal_set(box, EINA_TRUE); elm_box_padding_set(box, 3, 0); evas_object_show(box); elm_object_part_content_set(layout, "elm.swallow.content", box); for (i = 0; i < 10; ++i) { rect[i] = evas_object_rectangle_add(evas_object_evas_get(layout)); evas_object_color_set(rect[i], 0, 255, 0, 75); evas_object_size_hint_min_set(rect[i], 20, 20); evas_object_show(rect[i]); elm_box_pack_end(box, rect[i]); } for (i = 0; i < 10; ++i) ad->rect[i] = rect[i]; slider = eext_circle_object_slider_add(layout, ad->circle_surface); eext_circle_object_value_min_max_set(slider, 0.0, 10.0); eext_circle_object_value_set(slider, 0.0); eext_rotary_object_event_activated_set(slider, EINA_TRUE); eext_circle_object_slider_step_set(slider, 1.0); evas_object_smart_callback_add(slider, "value,changed", _brightness_changed_cb, ad); nf_it = elm_naviframe_item_push(naviframe, _("Slider"), NULL, NULL, layout, "empty"); elm_naviframe_item_pop_cb_set(nf_it, _setting_finished_cb, ad); }
The _brightness_changed_cb() callback is called when the brightness value is changed. Here, the rectangles are redrawn using the eext_circle_object_value_get() function value.
static void _brightness_changed_cb(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; int i, value; value = eext_circle_object_value_get(obj); for (i = 0; i < 10; ++i) { if (i < value) evas_object_color_set(ad->rect[i], 0, 255, 0, 150); else evas_object_color_set(ad->rect[i], 0, 255, 0, 75); } }
Information View
When the information item is clicked, the information view is shown in the main view. The following figure illustrates the information view and its wireframe structure.
Figure: (Circle) Settings information view
The _setting_information_cb() function creates a layout whose name is slider_layout. The layout has two swallow parts for a scroller and a button. The scroller with the label set to elm.swallow.content and the button is set to elm.swallow.button with the bottom style.
static void _setting_information_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { char edj_path[PATH_MAX] = {0,}; appdata_s *ad = data; Evas_Object *naviframe = ad->naviframe; Evas_Object *layout = NULL; Evas_Object *label = NULL; Evas_Object *button = NULL; Evas_Object *scroller = NULL; Evas_Object *circle_scroller = NULL; Elm_Object_Item *nf_it = NULL; app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX); layout = elm_layout_add(naviframe); elm_layout_file_set(layout, edj_path, "info_layout"); evas_object_show(layout); scroller = elm_scroller_add(layout); evas_object_show(scroller); elm_object_part_content_set(layout, "elm.swallow.content", scroller); circle_scroller = eext_circle_object_scroller_add(scroller, ad->circle_surface); eext_circle_object_scroller_policy_set(circle_scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); eext_rotary_object_event_activated_set(circle_scroller, EINA_TRUE); label = elm_label_add(scroller); elm_label_line_wrap_set(label, ELM_WRAP_MIXED); elm_object_text_set(label, "This is setting application, " "By using the movement of the rotary, " "you can change the value of volume and brightness."); evas_object_show(label); elm_object_content_set(scroller, label); button = elm_button_add(layout); elm_object_style_set(button, "bottom/queue"); elm_object_text_set(button, "OK"); elm_object_part_content_set(layout, "elm.swallow.button", button); evas_object_smart_callback_add(button, "clicked", _button_clicked_cb, ad); evas_object_show(button); nf_it = elm_naviframe_item_push(naviframe, _("Slider"), NULL, NULL, layout, "empty"); }