Tizen Native API  6.0
Theme - Using extensions

Using extensions is extremely easy, discarding the part where you have to write the theme for them.

In the following example we'll be creating two buttons, one to load or unload our extension theme and one to cycle around three possible styles, one of which we created.

After including our one and only header we'll jump to the callback for the buttons. First one takes care of loading or unloading our extension file, relative to the default theme set (thus the NULL in the functions first parameter).

#include <Elementary.h>
static void
btn_extension_click_cb(void *data EINA_UNUSED, Evas_Object *btn, void *ev EINA_UNUSED)
{
   const char *lbl = elm_object_text_get(btn);

   if (!strncmp(lbl, "Load", 4))
     {
        elm_theme_extension_add(NULL, edj_path);
        elm_object_text_set(btn, "Unload extension");
     }
   else if (!strncmp(lbl, "Unload", 6))
     {
        elm_theme_extension_del(NULL, edj_path);
        elm_object_text_set(btn, "Load extension");
     }
}

The second button, as we said before, will just switch around different styles. In this case we have three of them. The first one is our custom style, named after something very unlikely to find in the default theme. The other two styles are the standard and one more, anchor, which exists in the default and is similar to the default, except the button vanishes when the mouse is not over it.

static void
btn_style_click_cb(void *data EINA_UNUSED, Evas_Object *btn, void *ev EINA_UNUSED)
{
   const char *styles[] = {
        "chucknorris",
        "default",
        "anchor"
   };
   static int sel_style = 0;

   sel_style = (sel_style + 1) % 3;
   elm_object_style_set(btn, styles[sel_style]);
}

So what happens if the style switches to our custom one when the extension is loaded? Elementary falls back to the default for the widget.

And the main function, simply enough, will create the window, set the buttons and their callbacks, and just to begin with our button styled we're also loading our extension at the beginning.

EAPI_MAIN int
elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
{
   Evas_Object *win, *box, *btn;

   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);

#ifdef PACKAGE_DATA_DIR
   elm_app_compile_data_dir_set(PACKAGE_DATA_DIR);
#endif
   if (ecore_file_exists("./theme_example.edj"))
     {
        strcpy(edj_path, "./theme_example.edj");
     }
   else
     {
        elm_app_info_set(elm_main, "elementary", "examples/theme_example.edj");
        snprintf(edj_path, sizeof(edj_path), "%s/examples/theme_example.edj",
                 elm_app_data_dir_get());
     }
   elm_theme_extension_add(NULL, edj_path);

   win = elm_win_util_standard_add("theme", "Theme example");
   elm_win_autodel_set(win, EINA_TRUE);

   box = elm_box_add(win);
   evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(win, box);
   evas_object_show(box);

   btn = elm_button_add(win);
   elm_object_text_set(btn, "Unload extension");
   elm_box_pack_end(box, btn);
   evas_object_show(btn);
   evas_object_smart_callback_add(btn, "clicked", btn_extension_click_cb, NULL);

   btn = elm_button_add(win);
   elm_object_text_set(btn, "Switch style");
   elm_object_style_set(btn, "chucknorris");
   elm_box_pack_end(box, btn);
   evas_object_show(btn);
   evas_object_smart_callback_add(btn, "clicked", btn_style_click_cb, NULL);

   evas_object_resize(win, 300, 320);
   evas_object_show(win);

   elm_run();

   return 0;
}
ELM_MAIN()

In this case we wanted to easily remove extensions, but all adding an extension does is tell Elementary where else it should look for themes when it can't find them in the default theme. Another way to do this is to set the theme search order using elm_theme_set(), but this requires that the developer is careful not to override any user configuration. That can be helped by adding our theme to the end of whatever is already set, like in the following snippet.

 char buf[4096];
 snprintf(buf, sizeof(buf), "%s:./theme_example.edj", elme_theme_get(NULL);
 elm_theme_set(NULL, buf);

If we were using overlays instead of extensions, the same thing applies, but the custom theme must be added to the front of the search path.

That's all. Boringly simple, and the full code in one piece can be found here.

And the code for our extension is here.