Scaling Edje Objects
This demonstrates how you can scale Edje objects. Scalability is important when building user interfaces for different environments, such as mobile phones and laptops.
The natural value of scale factors is 1.0. Scaling affects minimum and maximum part size and font size, and multiplies them.
You can disable scaling of certain parts.
Initializing the EDC File
Set up and prepare the EDC source code for loading the Edje objects in your application:
-
To demonstrate Edje scale usability, set up 2 groups. The first group contains only one scalable part.
group { name: "scale_group_1"; parts { part { name: "scalable_rect"; type: RECT; scale: 1; description { state: "default" 0.0; min: 16 16; max: 16 16; color: 0 0 255 255; } } } }
Figure: First scalable group
For this example, the group is used for showing Edje's global scale.
The other group is used for showing usability of the edje_object_scale() function. The group has 2 non-scalable parts (not_scalable_rect1 and not scalable_rect2), which are related to the scalable parts. It can be seen that scalability actually changes the scalable parts and all UI can be changed according to new relatives.
Scalability of certain parts is usually preset in the EDC source code with the scale property:
group { name: "scale_group_2"; parts { part { name: "not_scalable_rect1"; type: RECT; scale: 0; description { state: "default" 0.0; align: 0.0 0.5; min: 40 40; max: 40 40; color: 255 0 255 255; } } part { name: "scalable_rect"; type: RECT; scale: 1; description { state: "default" 0.0; align: 0.0 0.5; min: 25 19; max: 25 19; color: 0 255 255 255; rel1 { relative: 1.0 0.0; to_x: "not_scalable_rect1"; } } } part { name: "not_scalable_rect2"; type: RECT; scale: 0; description { state: "default" 0.0; align: 0.0 0.5; min: 40 40; max: 40 40; color: 255 0 255 255; rel1 { relative: 1.0 0.0; to_x: "scalable_rect"; } } } } }
Figure: Second scalable group
-
The base_scale factor can be used when the whole collection in the EDC file contains it:
collections { base_scale: 1.2; group { name: "scale_group_1"; } group { name: "scale_group_2"; } group { name: "main_layout"; } }
-
An application must contain controls, such as a spinner, to change the scale and see the result.
Add a box with 2 groups loaded as edje objects, and spinners for changing the scale values:
group { name: "main_application"; parts { part { name: "edje.swallow.content"; type: SWALLOW; description { state: "default" 0.0; align: 0.0 1.0; rel1 { relative: 0.0 1.0; offset: 0 20; to_y: "title2"; } } } part { name: "title1"; type: TEXT; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 100 32; color: 0 0 0 255; text { text: "edje scale:"; font: "Sans"; size: 16; } } } part { name: "title2"; type: TEXT; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 150 32; color: 0 0 0 255; rel1 { relative: 0.0 1.0; to_y: "scale.swallow"; } text { text: "edje object scale:"; font: "Sans"; size: 16; } } } part { name: "scale.swallow"; type: SWALLOW; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 220 48; rel1 { relative: 1.0 0.0; to_x: "title2"; to_y: "title1"; } rel2 { to_y: "title1"; } } } part { name: "scale.swallow2"; type: SWALLOW; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 220 48; rel1 { relative: 1.0 0.0; to: "title2"; } rel2 { to_y: "title2"; } } } } }
Figure: Main application layout
In the example, there are the following swallows:
- edje.swallow.content is used for the box containing the Edje objects.
- scale.swallow is used for the spinner that changes the scale value a loaded Edje object.
- scale.swallow2 is used for the spinner that changes the global scale, so changing this value changes the scale of all Edje objects if they do not have their own scales set using the edje_object_scale_set() function.
Initializing the Application
All application code lays in the create_base_gui() function that creates and loads all objects and forms, and creates application's main look.
-
Create a window and get the path to the EDJ file:
ad->win = elm_win_util_standard_add(PACKAGE, PACKAGE); elm_win_conformant_set(ad->win, EINA_TRUE); 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); } // Path to edj group with three groups app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX);
-
Set the conformant containing the main layout into the window:
ad->conform = elm_conformant_add(ad->win); elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW); elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE); evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, ad->conform); evas_object_show(ad->conform); // Main layout ad->main_layout = elm_layout_add(ad->win); evas_object_size_hint_weight_set(ad->main_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_layout_file_set(ad->main_layout, edj_path, "main_application"); elm_object_content_set(ad->conform, ad->main_layout); evas_object_show(ad->main_layout); app_get_resource(EDJ_FILE, edj_path, (int)PATH_MAX);
Note If you have layout for your window written in the EDC file, use and load it as Layout with Elementary layout API (using, for example, the elm_layout_add() , elm_object_style_set() , and elm_layout_file_set() functions). -
Add the box and set it into the edje.swallow.content main layout swallow:
// Add the box ad->box = elm_box_add(ad->main_layout); evas_object_size_hint_weight_set(ad->box, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(ad->box, EVAS_HINT_FILL, 0.0); elm_box_horizontal_set(ad->box, EINA_TRUE); evas_object_show(ad->box); // Set the box into the main layout elm_object_part_content_set(ad->main_layout, "edje.swallow.content", ad->box);
-
Load the Edje objects:
// Add group1 ad->edje_object_1 = edje_object_add(evas_object_evas_get(ad->win)); evas_object_size_hint_weight_set(ad->edje_object_1, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); edje_object_file_set(ad->edje_object_1, edj_path, "scale_group_1"); // Check object loading errors if (edje_object_load_error_get(ad->edje_object_1) != EDJE_LOAD_ERROR_NONE) { evas_object_del(ad->edje_object_1); return; } evas_object_show(ad->edje_object_1);
-
Pack the Edje objects into the box:
elm_box_pack_end(ad->box, ad->edje_object_1); elm_box_pack_end(ad->box, ad->edje_object_2);
-
Add 2 spinners that change the scale values:
ad->edje_scale = elm_spinner_add(ad->win); evas_object_size_hint_weight_set(ad->edje_scale, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->edje_scale, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_spinner_min_max_set(ad->edje_scale, 1, 300); elm_spinner_step_set(ad->edje_scale, 10); evas_object_show(ad->edje_scale); elm_spinner_value_set(ad->edje_scale, 100); elm_object_part_content_set(ad->main_layout, "scale.swallow", ad->edje_scale); ad->edje_object_scale = elm_spinner_add(ad->win); evas_object_size_hint_weight_set(ad->edje_object_scale, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->edje_object_scale, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_spinner_min_max_set(ad->edje_object_scale, 1, 300); elm_spinner_step_set(ad->edje_object_scale, 10); evas_object_show(ad->edje_object_scale); elm_spinner_value_set(ad->edje_object_scale, 100); elm_object_part_content_set(ad->main_layout, "scale.swallow2", ad->edje_object_scale);
-
Display the window:
evas_object_show(ad->win);
Figure: Scale testing application
Setting Global Scales
-
Add a callback for the first spinner that changes Edje global scale value and, as a result, affects all loaded Edje objects:
static void create_base_gui(appdata_s *ad) { // Add scale spinners ad->edje_scale = elm_spinner_add(ad->win); evas_object_size_hint_weight_set(ad->edje_scale, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->edje_scale, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_spinner_min_max_set(ad->edje_scale, 1, 300); elm_spinner_step_set(ad->edje_scale, 10); evas_object_show(ad->edje_scale); elm_spinner_value_set(ad->edje_scale, 100); elm_object_part_content_set(ad->main_layout, "scale.swallow", ad->edje_scale); evas_object_smart_callback_add(ad->edje_scale, "changed", _on_global_scale_change, ad); }
-
Set the scale using the edje_scale_set() function:
static void _on_global_scale_change(void *data, Evas_Object *obj, void *event_info) { edje_scale_set(elm_spinner_value_get(obj) / 100); }
By clicking the spinner buttons, you can change the scale of all loaded Edje objects. The Edje object on the right has its own scale values, so global scale values do not apply to it.
Figure: Different global scales
Note |
---|
Using the edje_scale_set() function that changes the global scale values can affect your whole application and destroy the UI layout. Be careful with this function. |
Setting Scales for Edje Objects
Add a callback to get the value of the second spinner and apply it to the Edje object on the right:
static void _on_scale_change(void *data, Evas_Object *obj, void *event_info) { appdata_s *ad = data; edje_object_scale_set(ad->edje_object_2, elm_spinner_value_get(obj) / 100); } static void create_base_gui(appdata_s *ad) { // Add scale spinners ad->edje_object_scale = elm_spinner_add(ad->win); evas_object_size_hint_weight_set(ad->edje_object_scale, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_size_hint_align_set(ad->edje_object_scale, EVAS_HINT_FILL, EVAS_HINT_FILL); elm_spinner_min_max_set(ad->edje_object_scale, 1, 300); elm_spinner_step_set(ad->edje_object_scale, 10); evas_object_show(ad->edje_object_scale); elm_spinner_value_set(ad->edje_object_scale, 100); elm_object_part_content_set(ad->main_layout, "scale.swallow2", ad->edje_object_scale); evas_object_smart_callback_add(ad->edje_object_scale, "changed", _on_scale_change, ad); }
By clicking on spinner buttons, you can change the scale of the second Edje object in the box.
Figure: Edje object scales
Personal, Global, and Base Scales
Modify the main layout and add a swallow for the buttons. The buttons are used for showing the current scale:
-
Modify the main layout EDC code by creating another swallow part, swallow.buttons , and modifying the edje.swallow.content part:
group { name: "main_application"; parts { part { name: "edje.swallow.content"; type: SWALLOW; description { state: "default" 0.0; align: 0.0 1.0; rel1 { relative: 0.0 1.0; offset: 0 20; to_y: "title2"; } rel2 { relative: 1.0 0.0; to_y: "swallow.buttons"; } } } part { name: "title1"; type: TEXT; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 100 32; color: 0 0 0 255; text { text: "edje scale:"; font: "Sans"; size: 16; } } } part { name: "title2"; type: TEXT; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 150 32; color: 0 0 0 255; rel1 { relative: 0.0 1.0; to_y: "scale.swallow"; } text { text: "edje object scale:"; font: "Sans"; size: 16; } } } part { name: "scale.swallow"; type: SWALLOW; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 220 48; rel1 { relative: 1.0 0.0; to_x: "title2"; to_y: "title1"; } rel2 { to_y: "title1"; } } } part { name: "scale.swallow2"; type: SWALLOW; scale: 1; description { state: "default" 0.0; align: 0.0 0.0; max: 220 48; rel1 { relative: 1.0 0.0; to: "title2"; } rel2 { to_y: "title2"; } } } part { name: "swallow.buttons"; type: SWALLOW; scale: 0; description { state: "default" 0.0; align: 0.0 1.0; min: 0 60; max: -1 60; } } } }
-
Add a box with buttons and set it into the main layout:
static void _edje_object_scale_get(void *data, Evas_Object *obj, void *event_info) { char title[PATH_MAX] = {0, }; appdata_s *ad = data; snprintf(title, (int)PATH_MAX, "object %.2f", edje_object_scale_get(ad->edje_object_2)); elm_object_text_set(obj, title); } static void _edje_scale_get(void *data, Evas_Object *obj, void *event_info) { char title[PATH_MAX] = {0, }; snprintf(title, (int)PATH_MAX, "global %.2f", edje_scale_get()); elm_object_text_set(obj, title); } static void _edje_object_base_scale_get(void *data, Evas_Object *obj, void *event_info) { char title[PATH_MAX] = {0, }; appdata_s *ad = data; snprintf(title, (int)PATH_MAX, "base %.2f", edje_object_base_scale_get(ad->edje_object_2)); elm_object_text_set(obj, title); } static void create_base_gui(appdata_s *ad) { Evas_Object *box, *button; // Add the box box = elm_box_add(ad->main_layout); evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, 0.0); evas_object_size_hint_align_set(box, EVAS_HINT_FILL, 0.0); elm_box_horizontal_set(box, EINA_TRUE); evas_object_show(box); elm_object_part_content_set(ad->main_layout, "swallow.buttons", box); button = elm_button_add(ad->main_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "object "); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_object_scale_get, ad); elm_box_pack_end(box, button); button = elm_button_add(ad->main_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "global "); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_scale_get, ad); elm_box_pack_end(box, button); button = elm_button_add(ad->main_layout); evas_object_size_hint_align_set(button, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_weight_set(button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_text_set(button, "base "); evas_object_show(button); evas_object_smart_callback_add(button, "clicked", _edje_object_base_scale_get, ad); elm_box_pack_end(box, button); }
Clicking a button gets a specific scale and prints its value on the button. For example, clicking the Global button shows the global scale value.
Figure: Scale values
-
The loaded Edje object does not have its own scale value (0.00), so it uses the global scale value defined in the EFL configuration based on the device. A mobile device that is being used here, has the global scale ~1.8). The base scale is set to 1.2.
collections { base_scale: 1.2; group { name: "scale_group_1"; } group { name: "scale_group_2"; } group { name: "main_layout"; } }
Figure: Scale values after changing the Edje object scale
After applying the scale of the new object, the global scale does not apply to this Edje object anymore. While all other objects have the scale value 1.8, the new object has the scale value 1.37.
Note The default base scale value is 1.0. All scale values in Edje objects, either set with the global scale value using the edje_scale_set() function or with a personal scale factor using the edje_object_scale_set() function are divided by base scale. Figure: Base scale
Setting a scale value that is same as the base scale makes the layout appear as if it had the scale value 1.0.