(Circle) Settings UI Sample Overview

Wearable native

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

(Circle) Settings main view

(Circle) Settings tree

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

(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

(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

(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");
}