The [UI Sample] Calculator sample demonstrates how to implement a complex view using EFL UI components and containers.
It uses UI components, such as elm_conform and elm_panel for the view management, containers, such as elm_grid and elm_table for UI component management inside the view, and UI components, such as elm_button and elm_entry for the content inside the view.
The following figure illustrates the main view of the [UI Sample] Calculator sample application, its wireframe structure, and the UI component tree.
Figure: [UI Sample] Calculator screen
Application Layout
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 decorate the window with an indicator. The window contains a grid structure for the calculator entry display and its button panel. The entry display is aligned to the top of the grid and the button panel to the bottom of the grid.
static void create_base_gui(appdata_s *ad) { Evas_Object *grid, *panel; 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, "wm,rotation,changed", rotation_cb, ad); evas_object_smart_callback_add(ad->win, "delete,request", win_delete_request_cb, NULL); eext_object_event_callback_add(ad->win, EEXT_CALLBACK_BACK, win_back_cb, ad); ad->bg = create_bg(ad->win); ad->conform = create_conform(ad->win); elm_win_conformant_set(ad->win, EINA_TRUE); elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW); // Grid grid = elm_grid_add(ad->conform); evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_content_set(ad->conform, grid); // Entry ad->entry = create_entry(grid); elm_grid_pack(grid, ad->entry, 5, 5, 90, 25); // Panel panel = create_panel(grid, ad); elm_grid_pack(grid, panel, 0, 35, 100, 65); // Show the window after the base GUI is set up evas_object_show(ad->win); }
Main View
The create_entry() function creates the calculator display. Input for the display is created with calculator buttons created in the next steps, so there is no need for the software keypad. Disable the software keypad by setting the elm_entry_editable_set() function as false. The display uses a right-aligned, 50 pt font.
static Evas_Object * create_entry(Evas_Object *parent) { Evas_Object *entry; entry = elm_entry_add(parent); elm_entry_editable_set(entry, EINA_FALSE); elm_entry_entry_set(entry, "<font_size=50><align=right></font_size>"); evas_object_show(entry); return entry; }
The create_panel() function creates the calculator button panel. There are 2 sets of buttons: basic buttons that are always visible, and advanced buttons that are only visible in the landscape mode.
static Evas_Object * create_panel(Evas_Object *parent, appdata_s *ad) { Evas_Object *panel, *grid, *content; // Panel panel = elm_panel_add(parent); elm_panel_orient_set(panel, ELM_PANEL_ORIENT_BOTTOM); evas_object_show(panel); // Grid grid = elm_grid_add(panel); evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_content_set(panel, grid); // Panel basic content ad->basic_content = create_panel_basic_content(grid, ad); evas_object_size_hint_weight_set(ad->basic_content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->basic_content, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_grid_pack(grid, ad->basic_content, 3, 3, 94, 94); // Panel advanced content ad->advanced_content = create_panel_advanced_content(grid, ad); evas_object_size_hint_weight_set(ad->advanced_content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->advanced_content, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_grid_pack(grid, ad->advanced_content, -100, -100, 94, 94); return panel; }
The create_panel_basic_content() function creates the calculator buttons, such as number and sign buttons. The buttons are arranged in a table structure with a 10-pixel padding.
static Evas_Object * create_panel_basic_content(Evas_Object *parent, appdata_s *ad) { Evas_Object *table, *button; table = elm_table_add(parent); elm_table_padding_set(table, 10, 10); button = elm_button_add(table); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_text_set(button, "<font_size = 50>C</font_size>"); evas_object_smart_callback_add(button, "clicked", clicked_c_cb, ad->entry); evas_object_show(button); elm_table_pack(table, button, 0, 0, 1, 1); button = elm_button_add(table); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_object_text_set(button, "<font_size = 50>/</font_size>"); evas_object_smart_callback_add(button, "clicked", clicked_divide_cb, ad->entry); evas_object_show(button); elm_table_pack(table, button, 1, 0, 1, 1); … evas_object_show(table); return table; }
As an example, when the user clicks the 0 button, the clicked_0_cb() function is called. The function adds the text in the entry display.
static void clicked_0_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Evas_Object *entry = data; elm_entry_entry_append(entry, "<font_size = 50>0</font_size>"); }
When the user rotates the device, the rotation_cb() function is called, which changes the layout of contents. If the new layout is in the landscape mode, the advanced content is aligned at the left side of the basic content.
static void rotation_cb(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; int current_degree = elm_win_rotation_get(obj); if (current_degree != 0 && current_degree != 180) { elm_grid_pack_set(ad->basic_content, 45, 3, 52, 94); elm_grid_pack_set(ad->advanced_content, 3, 3, 36, 94); } else { elm_grid_pack_set(ad->basic_content, 3, 3, 94, 94); elm_grid_pack_set(ad->advanced_content, -100, -100, 94, 94); } }