elm-theme-viewer/src/bin/gui.c

754 lines
20 KiB
C

#include <Elementary.h>
#include <string.h>
#include "common.h"
int _gui_init_count = 0;
Gui_Data *gd = NULL;
extern ETV_Data *ed;
#define ETV_CHECK_GUI \
if (!gd) \
{ \
CRI("Gui is not initialized. Call gui_init() before you use it."); \
return; \
}
static void _gui_widget_load(void);
int
gui_init(void)
{
if (!gd)
{
gd = calloc(1, sizeof(Gui_Data));
if (!gd)
{
CRI("Internal Gui_Data is not created!");
return -1;
}
}
return ++_gui_init_count;
}
void
gui_shutdown(void)
{
if (_gui_init_count < 0)
{
CRI("gui_shutdown() is called more than gui_init() call.");
return;
}
ETV_SAFE_FREE(gd, free);
_gui_init_count--;
}
void
gui_version_set(Eina_Bool version)
{
ETV_CHECK_GUI;
gd->m_version = version;
}
// logo
static Evas_Object *
_logo_create(Evas_Object *parent)
{
Evas_Object *o = NULL, *box = NULL;
char buf[PATH_MAX] = { 0 };
box = o = elm_box_add(parent);
EXPAND(o); FILL(o);
evas_object_show(o);
o = elm_image_add(box);
WEIGHT(o, EVAS_HINT_EXPAND, 2.0); FILL(o);
snprintf(buf, PATH_MAX, "%s/images/logo.png", elm_app_data_dir_get());
elm_image_file_set(o, buf, NULL);
elm_box_pack_end(box, o);
evas_object_show(o);
o = elm_label_add(box);
EXPAND(o); FILL(o);
elm_object_text_set(o, "<font_size=20>Elm Theme Viewer v0.1</font_size>");
elm_box_pack_end(box, o);
evas_object_show(o);
return box;
}
static void
_preview_create(Widget_Type widget, const char *style)
{
char buf[PATH_MAX] = { 0 };
ETV_SAFE_FREE(gd->preview_obj, evas_object_del);
gd->widget = widget;
gd->style = style;
if (widget && style)
{
gd->preview_obj = widget_create(gd->preview_box, widget, style);
//elm_bg_color_set(gd->preview_bg, 255, 0, 0);
snprintf(buf, PATH_MAX, "%s/images/pm_fill.png", elm_app_data_dir_get());
elm_bg_file_set(gd->preview_bg, buf, NULL);
elm_bg_option_set(gd->preview_bg, ELM_BG_OPTION_TILE);
}
else
{
gd->preview_obj = _logo_create(gd->preview_box);
//elm_bg_color_set(gd->preview_bg, -1, -1, -1);
elm_bg_file_set(gd->preview_bg, NULL, NULL);
}
// preview_obj can be NULL (ex: inwin)
if (gd->preview_obj)
elm_box_pack_end(gd->preview_box, gd->preview_obj);
}
void
gui_preview_update(void)
{
_preview_create(gd->widget, gd->style);
}
// refresh the widget list when search entry is changed by user
static void
_entry_changed_cb(void *data EINA_UNUSED, Evas_Object *obj,
void *event_info EINA_UNUSED)
{
gd->search_widget_name = elm_entry_entry_get(obj);
elm_list_clear(gd->list);
elm_list_go(gd->list);
_gui_widget_load();
}
Evas_Object *
gui_widget_menu_create(Evas_Object *parent)
{
Evas_Object *nf = NULL, *box = NULL, *o = NULL;
gd->widget_naviframe = nf = elm_naviframe_add(parent);
evas_object_show(nf);
box = o = elm_box_add(nf);
evas_object_show(o);
o = elm_entry_add(box);
WEIGHT(o, EVAS_HINT_EXPAND, 0.0); FILL(o);
elm_entry_single_line_set(o, EINA_TRUE);
elm_entry_scrollable_set(o, EINA_TRUE);
elm_object_part_text_set(o, "guide", "Search widget here!");
evas_object_smart_callback_add(o, "changed,user", _entry_changed_cb, NULL);
elm_box_pack_end(box, o);
evas_object_show(o);
gd->list = o = elm_list_add(box);
elm_list_select_mode_set(o, ELM_OBJECT_SELECT_MODE_ALWAYS);
EXPAND(o); FILL(o);
elm_box_pack_end(box, o);
evas_object_show(o);
// fill in the widget list
_gui_widget_load();
elm_naviframe_item_push(nf, "Widgets", NULL, NULL, box, NULL);
return nf;
}
Evas_Object *
gui_preview_create(Evas_Object *parent)
{
Evas_Object *o = NULL, *fr = NULL, *tb = NULL;
fr = o = elm_frame_add(parent);
elm_object_text_set(o, "Preview");
evas_object_show(o);
tb = o = elm_table_add(fr);
elm_object_content_set(fr, o);
evas_object_show(o);
gd->preview_bg = o = elm_bg_add(tb);
EXPAND(o); FILL(o);
elm_table_pack(tb, o, 0, 0, 1, 1);
evas_object_show(o);
gd->preview_box = o = elm_box_add(tb);
EXPAND(o); FILL(o);
elm_table_pack(tb, o, 0, 0, 1, 1);
evas_object_show(o);
gd->preview_obj = _logo_create(gd->preview_box);
elm_box_pack_end(gd->preview_box, gd->preview_obj);
return fr;
}
void
gui_preview_focus(void)
{
elm_object_focus_set(gd->preview_obj, EINA_TRUE);
}
void
gui_panes_clicked_double_cb(void *data EINA_UNUSED, Evas_Object *obj,
void *event_info EINA_UNUSED)
{
static Eina_Bool contracted = EINA_FALSE;
Evas_Coord miny = 0, panel_h = 0;
double size = 0.0;
static double prev_size = 0.0;
if (!contracted)
{
prev_size = elm_panes_content_left_size_get(obj);
if (gd->preview_box)
{
evas_object_size_hint_min_get(gd->preview_box, NULL, &miny);
if (miny <= 0)
miny = 50 * elm_config_scale_get();
evas_object_geometry_get(obj, NULL, NULL, NULL, &panel_h);
size = miny / (double)panel_h;
}
elm_panes_content_left_size_set(obj, size);
}
else
{
elm_panes_content_left_size_set(obj, prev_size);
}
contracted = !contracted;
INF("size y %f %d", size, contracted);
}
/**
* GUI Open File
*/
static void
_gui_open_file_done_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info)
{
const char *file = event_info;
if (file)
{
}
evas_object_del(data);
}
static Eina_Bool
_edje_filter(const char *path, Eina_Bool dir, void *data EINA_UNUSED)
{
if (dir) return EINA_TRUE;
if (eina_str_has_extension(path, ".edj"))
return EINA_TRUE;
return EINA_FALSE;
}
static void
_gui_open_file(void)
{
Evas_Object *popup = NULL, *table = NULL, *fs = NULL;
popup = elm_popup_add(gd->win);
elm_object_part_text_set(popup, "title,text", "Open Theme File");
evas_object_show(popup);
fs = elm_fileselector_add(popup);
elm_fileselector_path_set(fs, getenv("HOME"));
elm_fileselector_custom_filter_append(fs, _edje_filter, NULL, "Theme Files");
elm_fileselector_is_save_set(fs, EINA_FALSE);
evas_object_smart_callback_add(fs, "done", _gui_open_file_done_cb, popup);
evas_object_show(fs);
table = util_elm_min_set(fs, 300, 400);
elm_object_content_set(popup, table);
}
static void
_toolbar_open_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info)
{
Elm_Object_Item *it = event_info;
if (!it) return;
elm_toolbar_item_selected_set(it, EINA_FALSE);
_gui_open_file();
}
static void
_toolbar_option_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info)
{
Elm_Object_Item *it = event_info;
elm_toolbar_item_selected_set(it, EINA_FALSE);
option_gui_create();
}
static void
_toolbar_about_btn_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
evas_object_del(data);
}
static void
_toolbar_about_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info)
{
Elm_Object_Item *it = event_info;
Evas_Object *o = NULL, *btn = NULL;
if (!it) return;
elm_toolbar_item_selected_set(it, EINA_FALSE);
o = elm_popup_add(gd->win);
elm_object_part_text_set(o, "title,text", "About");
elm_object_text_set(o, "Elm Theme Viewer v0.1 "
"@copyright 2012-2015. "
"Elm Theme Viewer team led<br>"
"by Daniel Juyung Seo.");
btn = elm_button_add(o);
elm_object_text_set(btn, "Close");
evas_object_smart_callback_add(btn, "clicked",
_toolbar_about_btn_cb, o);
elm_object_part_content_set(o, "button1", btn);
evas_object_show(btn);
evas_object_show(o);
}
static void
_toolbar_exit_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
elm_exit();
}
static void
_widget_description_create(void)
{
Evas_Object *o = NULL, *fr = NULL;
if (gd->left_menu_widget_desc) return;
// description
fr = o = elm_frame_add(gd->left_menu_box);
elm_object_text_set(o, "Widget Description");
evas_object_show(o);
gd->desc_scr = o = elm_scroller_add(fr);
elm_scroller_bounce_set(o, EINA_FALSE, EINA_FALSE);
elm_object_content_set(fr, o);
evas_object_show(o);
gd->desc_lbl = o = elm_label_add(gd->desc_scr);
elm_label_line_wrap_set(o, ELM_WRAP_MIXED);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_object_content_set(gd->desc_scr, o);
evas_object_show(o);
o = util_elm_min_set(fr, 0, WIDGET_DESC_HEIGHT);
WEIGHT(o, EVAS_HINT_EXPAND, 0.0); FILL(o);
elm_box_pack_end(gd->left_menu_box, o);
gd->left_menu_widget_desc = EINA_TRUE;
}
static void
_right_panes_content_create(Evas_Object *panes)
{
Evas_Object *o = NULL, *fr = NULL;
// preview
elm_object_part_content_set(panes, PANES_TOP, gui_preview_create(panes));
// description
fr = o = elm_frame_add(panes);
elm_object_text_set(o, "Widget Option");
evas_object_show(o);
gd->widget_option_scr = o = elm_scroller_add(fr);
elm_scroller_bounce_set(o, EINA_FALSE, EINA_FALSE);
evas_object_show(o);
elm_object_content_set(fr, o);
elm_object_part_content_set(panes, PANES_BOTTOM, fr);
}
void
gui_create(const char *edje_file,
Evas_Coord width, Evas_Coord height,
Eina_Bool fullscreen)
{
Evas_Object *o = NULL, *conform = NULL, *box = NULL, *lbox = NULL;
Evas_Object *panes = NULL;
Elm_Object_Item *it = NULL;
char path[PATH_MAX];
if (!edje_file) return;
ETV_CHECK_GUI;
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
// Window
gd->win = o = elm_win_util_standard_add("elm-theme-viewer", "Elm Theme Viewer");
elm_win_autodel_set(o, EINA_TRUE);
if (fullscreen)
elm_win_fullscreen_set(o, EINA_TRUE);
else
evas_object_resize(o, width, height);
o = evas_object_image_add(evas_object_evas_get(gd->win));
snprintf(path, sizeof(path),
"%s/images/ETV_logo_s.png", elm_app_data_dir_get());
evas_object_image_file_set(o, path, NULL);
elm_win_icon_object_set(gd->win, o);
evas_object_show(o);
// Conformant
conform = o = elm_conformant_add(gd->win);
EXPAND(o);
elm_win_resize_object_add(gd->win, o);
evas_object_show(o);
// Outer Vertical Box
box = o = elm_box_add(conform);
elm_object_content_set(conform, o);
evas_object_show(o);
o = elm_toolbar_add(box);
elm_toolbar_align_set(o, 0.0);
it = elm_toolbar_item_append(o, "document-open", "Open", _toolbar_open_cb, NULL);
elm_object_item_disabled_set(it, EINA_TRUE);
elm_toolbar_item_append(o, "edit", "Option", _toolbar_option_cb, NULL);
it = elm_toolbar_item_append(o, NULL, "Code", NULL, NULL);
elm_object_item_disabled_set(it, EINA_TRUE);
elm_toolbar_item_append(o, "media_player/info", "About", _toolbar_about_cb, NULL);
elm_toolbar_item_append(o, "close", "Exit", _toolbar_exit_cb, NULL);
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
elm_box_pack_end(box, o);
evas_object_show(o);
// Main Layout
gd->gui_layout = o = elm_layout_add(gd->win);
snprintf(path, sizeof(path), "%s/themes/layout.edj", elm_app_data_dir_get());
elm_layout_file_set(o, path, "etv/main/layout");
EXPAND(o); FILL(o);
elm_box_pack_end(box, o);
evas_object_show(o);
// title text
elm_layout_text_set(gd->gui_layout, "edje_name_txt", edje_file);
// Panes for preview and menu
panes = o = elm_panes_add(gd->gui_layout);
elm_panes_content_left_min_size_set(o, ELM_SCALE_SIZE(200));
elm_panes_content_left_size_set(o, 0.1);
evas_object_show(o);
evas_object_smart_callback_add(o, "clicked,double",
gui_panes_clicked_double_cb, o);
elm_layout_content_set(gd->gui_layout, "preview", o);
// Widget Box (Left)
gd->left_menu_box = lbox = o = elm_box_add(panes);
evas_object_show(o);
elm_object_part_content_set(panes, "left", o);
o = gui_widget_menu_create(lbox);
EXPAND(o); FILL(o);
elm_box_pack_end(lbox, o);
evas_object_show(o);
// Preview Box (Right)
o = elm_panes_add(panes);
elm_panes_horizontal_set(o, EINA_TRUE);
elm_panes_content_left_size_set(o, 0.7);
_right_panes_content_create(o);
evas_object_show(o);
elm_object_part_content_set(panes, "right", o);
evas_object_show(gd->win);
INF("GUI Creation Done");
return;
}
static const char *
_gui_description_text_get(void)
{
const char *txt = NULL;
if (!ed->selected_widget_type)
return "Widget is not selected.";
txt = widget_desc_get_by_type(ed->selected_widget_type);
if (!txt)
return "There is no description for this widget.";
else
return txt;
}
Evas_Object *
gui_description_label_get(void)
{
Evas_Object *o;
o = elm_label_add(gd->win);
elm_label_line_wrap_set(o, ELM_WRAP_MIXED);
elm_object_text_set(o, _gui_description_text_get());
evas_object_show(o);
return o;
}
void
gui_description_set()
{
elm_object_text_set(gd->desc_lbl, _gui_description_text_get());
elm_scroller_region_show(gd->desc_scr, 0, 0, 1, 1);
}
/*
* called when the widget style list item is selected.
*/
static void
_style_list_sel_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Style_Data *sd = data;
if (!data || !sd->widget_type || !sd->wds->style) return;
INF("%s %s", widget_name_get_by_type(sd->widget_type), sd->wds->style);
_preview_create(sd->widget_type, sd->wds->style);
widget_option_content_update(sd->widget_type);
}
static void
_nf_prev_btn_clicked_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
elm_win_focus_highlight_enabled_set(gd->win, option_focus_highlight_get());
elm_win_focus_highlight_animate_set(gd->win, option_focus_highlight_animate_get());
if (elm_config_access_get())
elm_config_access_set(EINA_FALSE);
ed->selected_widget_type = ETV_ID_NONE;
_preview_create(ETV_ID_NONE, NULL);
widget_option_content_update(ETV_ID_NONE);
gui_description_set();
elm_naviframe_item_pop(data);
}
/*
static void
_style_list_gengrid_group_index_sel_cb(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
_preview_create(ETV_ID_GENGRID, "h9 group-index-style");
}
static void
_style_list_gengrid_grid_check_sel_cb(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
_preview_create(ETV_ID_GENGRID, "h9 grid-check-style");
}
static void
_custom_styles_add(Evas_Object *list, Widget_Type widget)
{
if (ETV_ID_GENGRID == widget)
{
elm_list_item_append(list, "(H9) Grid Check Style", NULL, NULL,
_style_list_gengrid_grid_check_sel_cb, NULL);
elm_list_item_append(list, "(H9) Group Index Style", NULL, NULL,
_style_list_gengrid_group_index_sel_cb, NULL);
}
}
*/
static Eina_Bool
_gui_widget_style_exclude_check(Widget_Type type, const char *style)
{
switch (type)
{
case ETV_ID_POPUP:
if (!strncmp("buttons1/", style, strlen("buttons1/")) ||
!strncmp("buttons2/", style, strlen("buttons2/")) ||
!strncmp("buttons3/", style, strlen("buttons3/")) ||
!strncmp("content/", style, strlen("content/")) ||
!strncmp("item/", style, strlen("item/"))
)
return EINA_TRUE;
default:
return EINA_FALSE;
}
}
static char *
_gl_text_get_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *part)
{
Style_Data *sd = data;
Widget_Data_Style *wds = sd->wds;
if (!strcmp(part, "elm.text"))
return strdup(wds->simple);
else
return strdup(wds->group);
}
static void
_gl_del_cb(void *data, Evas_Object *obj EINA_UNUSED)
{
Style_Data *sd = data;
// do not need to free the internals of Style_Data
free(sd);
}
static Evas_Object *
_gui_widget_style_load(Evas_Object *parent, Widget_Type type)
{
Evas_Object *o = NULL;
Eina_List *styles = NULL, *l = NULL;
Widget_Data_Style *wds = NULL;
Style_Data *sd = NULL;
Elm_Genlist_Item_Class *itc = NULL;
itc = elm_genlist_item_class_new();
itc->item_style = "double_label";
itc->func.text_get = _gl_text_get_cb;
itc->func.content_get = NULL;
itc->func.state_get = NULL;
itc->func.del = _gl_del_cb;
// widget styles list
gd->left_menu_style_genlist = o = elm_genlist_add(parent);
elm_genlist_select_mode_set(o, ELM_OBJECT_SELECT_MODE_ALWAYS);
styles = theme_widget_styles_get(type);
EINA_LIST_FOREACH(styles, l, wds)
{
if (_gui_widget_style_exclude_check(type, wds->style))
continue;
// TODO: sd needs to be freed properly
sd = (Style_Data *)calloc(1, sizeof(Style_Data));
sd->widget_type = type;
sd->wds = wds;
elm_genlist_item_append(o, itc, sd, NULL, ELM_GENLIST_ITEM_NONE,
_style_list_sel_cb, sd);
}
// add additional hacky custom styles for special reasons
//_custom_styles_add(o, type);
elm_genlist_item_selected_set(elm_genlist_first_item_get(o), EINA_TRUE);
elm_genlist_item_class_free(itc);
return o;
}
/*
* called when the widget list item is selected.
*/
static void
_widget_list_sel_cb(void *data, Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Evas_Object *nf = gd->widget_naviframe;
Evas_Object *li, *prev_btn;
Elm_Object_Item *it;
Widget_Type type = (Widget_Type)data;
if (!nf || !type) return;
ed->selected_widget_type = type;
// create list
li = _gui_widget_style_load(nf, type);
// prev button
prev_btn = elm_button_add(gd->win);
elm_object_text_set(prev_btn, "<");
evas_object_smart_callback_add(prev_btn, "clicked",
_nf_prev_btn_clicked_cb, nf);
evas_object_show(prev_btn);
if (ed->tizen)
{
it = elm_naviframe_item_push(nf, "Styles", NULL, NULL, li, NULL);
elm_object_style_set(prev_btn, "naviframe/back_btn/default");
elm_object_item_part_content_set(it, "title_left_btn", prev_btn);
elm_object_item_signal_emit(it,
"elm,state,toolbar,close,internal","elm");
}
else
{
it = elm_naviframe_item_push(nf, "Styles", prev_btn, NULL, li, NULL);
}
elm_object_item_part_text_set(it, "subtitle",
(char *)widget_name_get_by_type(type));
// create widget description frame
if (!gd->left_menu_widget_desc) _widget_description_create();
// set widget description
if (!gd->m_version)
gui_description_set();
else
{
// mobile version sets the guidescription on button click
}
}
/*
* widget list
*/
static void
_gui_widget_load(void)
{
Eina_List *l;
Widget_Data *wd;
Elm_Object_Item *it = NULL, *li_sel_it = NULL;
const char *widget_name = NULL;
EINA_LIST_FOREACH(widget_list, l, wd)
{
widget_name = widget_name_get_by_type(wd->type);
if (eina_list_count(wd->styles))
{
// filter searched widget
if (gd->search_widget_name &&
!strstr(widget_name, gd->search_widget_name)) continue;
it = elm_list_item_append(gd->list,
widget_name,
NULL, NULL,
_widget_list_sel_cb, (void *)wd->type);
if (wd->type == ed->start_widget_type)
li_sel_it = it;
}
}
elm_list_go(gd->list);
if (li_sel_it)
elm_list_item_selected_set(li_sel_it, EINA_TRUE);
}