
The (Circle) Buddy UI sample application demonstrates how you can create a buddy and draw a UI for the buddy.
For information on creating the sample application project in the IDE, see Creating Sample Applications.
The following figure illustrates the main screen of the Buddy UI.
Figure: (Circle) Buddy UI screens
_Buddy_UI/images/buddy_ui_views_wn.png)
The application opens with the main view where the user can view all buddies in a circular list. To view the details of a specific buddy, click the buddy in the main view.
Source Files
You can create and view the sample application project including the source files in the IDE.
| File name | Description |
|---|---|
| edje/images | This file contains the image files used in the main.edc file. |
| inc/buddyui.h | This file contains information and definition of the variables and functions used in the C files, especially in the buddyui.c 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/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/images | This directory contains the image files used in the C files. |
| src/buddyui.c | This file contains the functions related to the application life-cycle, callback functions, and view control. |
| src/data.c | This file contains the functions for retrieving and creating data for the application. |
| src/view.c | This file contains the functions for implementing the views and handling events. |
Implementation
Application Layout
To create the basic layout, use the view_create() function. The window and conformant components are essential parts of the application layout.
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");
return;
}
// Show the window after the main view is set up
evas_object_show(s_info.win);
}
To manage multiple views efficiently, you need a naviframe component. To create the naviframe and a circular layout, use the view_buddy_create() function:
void view_buddy_create(void)
{
// Create the Eext circle surface
s_info.circle_surface = eext_circle_surface_conformant_add(s_info.conform);
// Create a circular layout
s_info.layout = view_create_layout_for_conformant_by_theme(s_info.conform);
// Create the naviframe
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);
s_info.win = NULL;
return;
}
}
Main View
The application opens with the main view.
Figure: Main view
_Buddy_UI/images/buddy_ui_main_view_wn.png)
To create the main view, use the view_buddy_create() function:
main_view_layout = view_create_layout(win, edj_path, GRP_MAIN, NULL, NULL);
The following figure shows the view frame created by the above code.
Figure: Main view frame
_Buddy_UI/images/buddy_ui_main_frame_wn.png)
To fill out each part of the view, use the _init_view() function:
- The view_set_label() function creates a label and sets it to the sw.focus.txt object.
- The third parameter of the view_set_label_text() function determines the focus of this view.
view_set_label(main_view_layout, "sw.focus.txt"); view_set_label_text(main_view_layout, "sw.focus.txt", item_info->name);
You can customize the _naviframe_main_view_pop_cb() callback to do something when you press the back key in the main view.
To manage the buddy list in the main view:
- Create the buddy item list in main the view with the following information structure:
typedef struct _item_info_s { int position; char *name; char *number; char *img_path; float w; float h; } item_info_s; - When the application is launched, the buddy items are created and appended to the item list.
item_count = data_get_item_total_count(); for (i = 0; i < item_count; i++) { Evas_Object *item_layout = NULL; item_info_s *item_info = malloc(sizeof(item_info_s)); item_info->name = data_get_item_name(i); item_info->number = data_get_item_number(i); item_info->img_path = data_get_item_image(i); item_info->w = 20; item_info->h = 20; item_layout = view_buddy_create_item_layout(main_view_layout, item_info->name, edj_path, item_info->img_path, default_img_path, NULL); evas_object_data_set(item_layout, "__ITEM_INFO__", item_info); data_push_item_to_list(&item_list, item_layout); } data_set_item_list(item_list); - If the application is terminated, the buddy items are destroyed:
item_list = data_get_item_list(); EINA_LIST_FREE(item_list, item) { item_info_s *item_info = evas_object_data_del(item, "__ITEM_INFO__"); if (item_info == NULL) { continue; } free(item_info->name); free(item_info->number); free(item_info->img_path); free(item_info); }
The position of the buddy on the screen is determined by a position index that a buddy item has.
Figure: Position index in the main view
_Buddy_UI/images/buddy_ui_position_wn.png)
When a rotary event is detected, buddy items are moved according to the direction of rotation. At this time, the buddy item position, size, transparency, and font size are set according to the location information matched with the index. The animation of the movement is implemented using the _simple_circle_animation() function of the Ecore Animator API.
static Eina_Bool
_simple_circle_path_animation(void *data)
{
Evas_Object *main_view_layout = data;
Eina_List *item_list = NULL;
Eina_List *l = NULL;
Evas_Object *item_layout = NULL;
static int frame = 0;
// After the last item, the circle path animation is finished
if (_check_last_item_in_list() == EINA_TRUE)
{
frame = 0;
s_info.anim = NULL;
s_info.anim_end = EINA_TRUE;
return ECORE_CALLBACK_CANCEL;
}
// If the current frame is over FRAME_MAX, circle path animation is finished
if (frame > FRAME_MAX)
{
frame = 0;
s_info.anim = NULL;
s_info.anim_end = EINA_TRUE;
return ECORE_CALLBACK_CANCEL;
}
else if (frame == 0)
{
_change_title_position(main_view_layout);
}
s_info.anim_end = EINA_FALSE;
item_list = data_get_item_list();
EINA_LIST_FOREACH(item_list, l, item_layout)
{
item_info_s *item_info = NULL;
int to_deg, to_x, to_y, to_w, to_h, to_opacity;
int from_deg, from_x, from_y, from_w, from_h, from_opacity;
int cur_x, cur_y, cur_w, cur_h;
int index, move_x, move_y, radius, opacity;
int x_coord, y_coord;
float deg_delta = 0.0f, angle = 0.0f;
item_info = evas_object_data_get(item_layout, "__ITEM_INFO__");
index = item_info->position;
if (frame == 0)
{
int font_size = data_get_position_font_size(data_get_next_index(s_info.rotary_direction, index));
view_buddy_change_item_font_size(item_layout, font_size);
}
else if (frame == FRAME_MAX)
{
_set_item_property(item_layout, data_get_next_index(s_info.rotary_direction, index));
if (data_get_next_index(s_info.rotary_direction, index) == 5)
{
view_set_label_text(main_view_layout, "sw.focus.txt", item_info->name);
dlog_print(DLOG_DEBUG, LOG_TAG, "item info : %s, %s", item_info->name, item_info->img_path);
}
continue;
}
data_get_position_info(index, &from_x, &from_y, &from_w, &from_h, &from_opacity);
data_get_position_info(data_get_next_index(s_info.rotary_direction, index), &to_x, &to_y, &to_w, &to_h, &to_opacity);
evas_object_geometry_get(item_layout, &cur_x, &cur_y, &cur_w, &cur_h);
// Get the degree of the item layout
from_deg = data_get_position_degree(index);
to_deg = data_get_position_degree(data_get_next_index(s_info.rotary_direction, index));
deg_delta = fabs((float) from_deg - (float) to_deg);
// Get the size of the item layout
if (index < 0 || index > 10)
{
item_info->w = 20;
item_info->h = 20;
}
else
{
data_get_item_size(&item_info->w, &item_info->h, from_w, from_h, to_w, to_h, deg_delta);
}
evas_object_resize(item_layout, item_info->w, item_info->h);
// Get the position of the item layout
if (index < 0 || index > 10)
{
x_coord = 360;
y_coord = 180;
}
else
{
// Calculate angle
angle = data_get_item_angle(from_deg, to_deg, deg_delta, frame);
// Calculate radius
radius = data_get_item_radius(index, s_info.rotary_direction, frame);
// Calculate position
data_get_simple_circle_path(&move_x, &move_y, radius, angle);
x_coord = move_x - (cur_w / 2);
y_coord = move_y - (cur_h / 2);
}
evas_object_move(item_layout, x_coord, y_coord);
// Get the opacity of the item layout
opacity = data_get_item_opacity(item_layout, from_opacity, to_opacity, deg_delta);
evas_object_color_set(item_layout, opacity, opacity, opacity, opacity);
evas_object_show(item_layout);
}
frame++;
return ECORE_CALLBACK_RENEW;
}
Detail View
To move to the detail view when the user clicks the focused buddy on the main view, register and customize the _focus_clicked_cb() callback:
view_set_customized_event_callback(main_view_layout, "mouse,clicked", "img.focus.bg", _focus_clicked_cb, main_view_layout);
In the callback, the detail view is created and shows the buddy item information.
Figure: Detail view
_Buddy_UI/images/buddy_ui_detail_view_wn.png)
To manage the view easily, add it to the naviframe:
view_push_item_to_naviframe(naviframe, detail_view_layout, _detail_view_pop_cb, main_view_layout);