(Circle) System Settings Sample Overview

Wearable native

The (Circle) System Settings UI sample application demonstrates how you can create a settings application. Especially, it demonstrates how to manage the naviframe and genlist components to create a complete view of the system settings application.

For information on creating the sample application project in the IDE, see Creating Sample Applications.

The following figure illustrates the main screens of the (Circle) System Settings UI.

Figure: (Circle) System Settings UI screens

(Circle) System Settings UI screens

The application opens with the main view that displays a selection of settings. Click a setting to view and change its related values.

Source Files

You can create and view the sample application project including the source files in the IDE.

Table: Source files
File name Description
edje/images This directory contains the image files used in the main.edc file.
inc/data.h This file contains information and definition of the variables and functions used in the C files, especially in the data.c file.
inc/systemsettings.h This file contains information and definition of the variables and functions used in the C files, especially in the main.c file.
inc/view.h This file contains information and definition of the variables and functions used in the C files, especially in the view.c file.
res/edje/main.edc This file is for the UI and contains style, image, and position of the sample application.
res/image This directory contains the image files used in the C files.
src/data.c This file contains the functions for retrieving and making data for the application.
src/main.c This file contains the functions related to the application life-cycle, callback functions, and view control.
src/view.c This file contains the functions for implementing the views and handling events.

Implementation

Application Layout

To create the system settings application, first create the application UI using the view_create() function.

The application starts with the main() function, where the life-cycle callbacks are registered. The app_create() callback function is called first. After that, the view_create() function creates the base UI of the application. The UI consists of window, conformant, layout, and naviframe components.

The wearable profile does not support the indicator function, which means that you must use the view_create_conformant_without_indicator() function to create a conformant that does not set the indicator mode. After that, you have to create a circle_surface to display a circular genlist.

void 
view_create(void)
{
   // Create a window
   s_info.win = view_create_win(PACKAGE);
   if (s_info.win == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a window.");

      return;
   }

   // Create a conformant
   s_info.conform = view_create_conformant_without_indicator(s_info.win);
   if (s_info.conform == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a conformant");
      evas_object_del(s_info.win);

      return;
   }

   // Create an Eext circle surface
   s_info.circle_surface = eext_circle_surface_conformant_add(s_info.conform);

   s_info.layout = view_create_layout_for_conformant(s_info.conform, NULL, NULL, NULL, NULL);

   s_info.nf = view_create_naviframe(s_info.layout);
   if (s_info.nf == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a naviframe.");
      evas_object_del(s_info.win);

      return;
   }

   // Show the window after the main view is set up
   evas_object_show(s_info.win);
}

To create a layout for the conformant, you can use 2 methods:

  • Create an EDJ file that you can customize.

    If you want to use a customized EDJ file, you must use the view_create_layout() function.

  • Use a premade EDJ file.

    The layout in this sample is created using a premade EDJ file. The style can be changed with the elm_layout_theme_set() function.

Evas_Object* 
view_create_layout_for_conformant(Evas_Object *parent, const char *file_name, const char *group_name, 
                                  Eext_Event_Cb cb_function, void *user_data)
{
   Evas_Object *layout = NULL;

   if (parent == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "parent is NULL.");

      return NULL;
   }

   if (file_name == NULL) 
   {
      layout = view_create_layout_by_theme(parent, "layout", "application", "default");
   } 
   else 
   {
      layout = view_create_layout(parent, file_name, group_name, cb_function, user_data);
   }

   if (layout == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "layout is NULL.");

      return NULL;
   }

   elm_object_content_set(parent, layout);

   return layout;
}

Creating a Genlist

The view_create_circle_genlist() function creates the genlist component, which sets the list mode with the elm_genlist_mode_set() function.

To display a circular genlist, create a circular genlist component supported by the Efl Extension API. The eext_circle_object_genlist_scroller_policy_set() function sets the scrollbar visibility policy.

Evas_Object*
view_create_circle_genlist(Evas_Object *parent)
{
   Evas_Object *genlist = NULL;
   Evas_Object *circle_genlist = NULL;

   if (parent == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "parent is NULL.");

      return NULL;
   }

   if (s_info.circle_surface == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "circle surface is NULL.");

      return NULL;
   }

   genlist = elm_genlist_add(parent);
   // Make the selected list item appear compressed
   elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS);
   evas_object_smart_callback_add(genlist, "selected", _gl_selected_cb, NULL);

   // Make the genlist style circular
   circle_genlist = eext_circle_object_genlist_add(genlist, s_info.circle_surface);
   eext_circle_object_genlist_scroller_policy_set(circle_genlist, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
   eext_rotary_object_event_activated_set(circle_genlist, EINA_TRUE);

   evas_object_show(genlist);

   return genlist;
}

Inserting Items to a Genlist

Insert an item to the genlist using the view_append_item_to_genlist() function:

void 
view_append_item_to_genlist(Evas_Object *genlist, const char *style,
                            const void *data, Evas_Smart_Cb _clicked_cb, const void *cb_data)
{
   Elm_Genlist_Item_Class *item_class = NULL;

   if (genlist == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "genlist is NULL.");

      return;
   }

   if (style == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "item style is NULL.");

      return;
   }

   item_class = _set_genlist_item_class(style);

   elm_genlist_item_append(genlist, item_class, data, NULL, ELM_GENLIST_ITEM_NONE, _clicked_cb, cb_data);

   elm_genlist_item_class_free(item_class);
}

Before the item is inserted into the genlist, the item class must be set. The _set_genlist_item_class() sets the class for each item and registers functions to get text and contents. These functions are called when the items are shown on the screen. The functions receive data in the elm_genlist_item_append() function as the third parameter.

static Elm_Genlist_Item_Class* 
_set_genlist_item_class(const char *style)
{
   Elm_Genlist_Item_Class *item_class = NULL;

   if (style == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "style is NULL.");

      return NULL;
   }

   item_class = elm_genlist_item_class_new();

   // Item class of the genlist must be added below
   // For more information on genlist styles, see Wearable UI Components

   if (!strcmp(style, "menu.title")) 
   {
      item_class->item_style = "title";
      // This function is operated when the item is shown on the screen to get the title
      item_class->func.text_get = data_get_menu_title_text;
   } 
   else if (!strcmp(style, "display.title")) 
   {
      item_class->item_style = "title";
      item_class->func.text_get = data_get_display_title_text;
   } 
   else if (!strcmp(style, "1text")) 
   {
      item_class->item_style = "1text";
      item_class->func.text_get = data_get_display_text;
   } 
   else if (!strcmp(style, "1text.1icon")) 
   {
      item_class->item_style = "1text.1icon";
      item_class->func.text_get = data_get_menu_text;
      item_class->func.content_get = _get_menu_icon;
   } 
   else if (!strcmp(style, "1text.1icon.1")) 
   {
      item_class->item_style = "1text.1icon.1";
      item_class->func.text_get = data_get_display_text;
      item_class->func.content_get = _get_display_icon;
   } 
   else if (!strcmp(style, "2text")) 
   {
      item_class->item_style = "2text";
      item_class->func.text_get = data_get_display_text;
   } 
   else if (!strcmp(style, "padding")) 
   {
      // "padding" style does nothing
      // It only places the genlist item in the middle of the screen
   }

   return item_class;
}

Inserting Items to a Naviframe

The genlist must be inserted into the naviframe component to be shown on the screen.

In the view_push_item_to_naviframe() function, the genlist is inserted into the navifame as a naviframe item using the elm_naviframe_item_push() function. The elm_naviframe_item_push() function puts a new item to the top of the naviframe stack and shows it. It returns the created item, and it can register a callback function to be called when the naviframe is going to be popped using the elm_naviframe_item_pop_cb_set() function.

void 
view_push_item_to_naviframe(Evas_Object *nf, Evas_Object *item, Elm_Naviframe_Item_Pop_Cb _pop_cb, 
                            void *cb_data)
{
   Elm_Object_Item* nf_it = NULL;

   if (nf == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "naviframe is NULL.");

      return;
   }

   if (item == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "item is NULL.");

      return;
   }

   nf_it = elm_naviframe_item_push(nf, NULL, NULL, NULL, item, "empty");
   elm_naviframe_item_pop_cb_set(nf_it, _pop_cb, cb_data);
}