You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

586 lines
16 KiB

#include "e.h"
typedef struct _E_Widget_Data E_Widget_Data;
typedef struct _Item Item;
struct _E_Widget_Data
{
Evas_Object *o_base, *o_box;
int icon_w, icon_h;
Eina_List *items;
Eina_Bool scrollable E_BITFIELD;
Eina_Bool focus_steal E_BITFIELD;
};
struct _Item
{
Evas_Object *o_toolbar, *o_base, *o_icon;
void (*func)(void *data1, void *data2);
const void *data1, *data2;
Eina_Bool selected E_BITFIELD;
};
static void _e_wid_del_hook(Evas_Object *obj);
static void _e_wid_focus_hook(Evas_Object *obj);
static void _e_wid_focus_steal(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _e_wid_disable_hook(Evas_Object *obj);
static void _e_wid_signal_cb1(void *data, Evas_Object *obj, const char *emission, const char *source);
static void _e_wid_cb_scrollframe_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _e_wid_cb_key_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
static void _e_wid_signal_prev(void *data, Evas_Object *obj, const char *emission, const char *source);
static void _e_wid_signal_next(void *data, Evas_Object *obj, const char *emission, const char *source);
static void _item_show(Item *it);
static void _item_select(Item *it);
static void _item_unselect(Item *it);
/* local subsystem functions */
/* externally accessible functions */
E_API Evas_Object *
e_widget_toolbar_add(Evas *evas, int icon_w, int icon_h)
{
Evas_Object *obj, *o;
E_Widget_Data *wd;
Evas_Coord mw = 0, mh = 0;
obj = e_widget_add(evas);
e_widget_del_hook_set(obj, _e_wid_del_hook);
e_widget_focus_hook_set(obj, _e_wid_focus_hook);
e_widget_disable_hook_set(obj, _e_wid_disable_hook);
wd = E_NEW(E_Widget_Data, 1);
e_widget_data_set(obj, wd);
wd->icon_w = icon_w;
wd->icon_h = icon_h;
wd->focus_steal = EINA_TRUE;
o = e_scrollframe_add(evas);
wd->o_base = o;
o = elm_box_add(e_win_evas_win_get(evas));
wd->o_box = o;
o = wd->o_base;
e_scrollframe_custom_theme_set(o, "base/theme/widgets", "e/widgets/toolbar");
e_scrollframe_single_dir_set(o, 1);
e_scrollframe_policy_set(o, E_SCROLLFRAME_POLICY_AUTO,
E_SCROLLFRAME_POLICY_OFF);
e_scrollframe_thumbscroll_force(o, 1);
evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE,
_e_wid_cb_scrollframe_resize, obj);
evas_object_event_callback_add(e_scrollframe_edje_object_get(wd->o_base),
EVAS_CALLBACK_MOUSE_DOWN,
_e_wid_focus_steal, obj);
evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
_e_wid_cb_key_down, obj);
edje_object_signal_callback_add(e_scrollframe_edje_object_get(o),
"e,action,prev", "e",
_e_wid_signal_prev, obj);
edje_object_signal_callback_add(e_scrollframe_edje_object_get(o),
"e,action,next", "e",
_e_wid_signal_next, obj);
evas_object_show(o);
e_widget_sub_object_add(obj, o);
e_widget_resize_object_set(obj, o);
o = wd->o_box;
elm_box_horizontal_set(o, 1);
elm_box_homogeneous_set(o, 1);
e_scrollframe_child_set(wd->o_base, o);
e_widget_sub_object_add(obj, o);
evas_object_show(o);
edje_object_size_min_calc(e_scrollframe_edje_object_get(wd->o_base),
&mw, &mh);
e_widget_size_min_set(obj, mw, mh);
return obj;
}
E_API const Eina_List *
e_widget_toolbar_items_get(Evas_Object *obj)
{
E_Widget_Data *wd;
if (!obj) return NULL;
if (!(wd = e_widget_data_get(obj))) return NULL;
return wd->items;
}
E_API unsigned int
e_widget_toolbar_items_count(Evas_Object *obj)
{
E_Widget_Data *wd;
if (!obj) return 0;
if (!(wd = e_widget_data_get(obj))) return 0;
return eina_list_count(wd->items);
}
E_API const char *
e_widget_toolbar_item_label_get(void *item)
{
Item *it = item;
if (!it) return NULL;
return edje_object_part_text_get(it->o_base, "e.text.label");
}
E_API void
e_widget_toolbar_item_append(Evas_Object *obj, Evas_Object *icon, const char *label, void (*func)(void *data1, void *data2), const void *data1, const void *data2)
{
E_Widget_Data *wd;
Evas_Object *o;
Item *it;
Evas_Coord mw = 0, mh = 0, vw = 0, vh = 0;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
o = edje_object_add(evas_object_evas_get(obj));
e_theme_edje_object_set(o, "base/theme/widgets",
"e/widgets/toolbar/item");
it = E_NEW(Item, 1);
it->o_toolbar = obj;
it->o_base = o;
it->o_icon = icon;
it->func = func;
it->data1 = data1;
it->data2 = data2;
wd->items = eina_list_append(wd->items, it);
edje_object_signal_callback_add(o, "e,action,click", "e",
_e_wid_signal_cb1, it);
if (icon)
{
evas_object_size_hint_min_set(icon, wd->icon_w, wd->icon_h);
edje_object_part_swallow(o, "e.swallow.icon", icon);
evas_object_show(icon);
edje_object_signal_emit(o, "e,icon,enabled", "e");
}
else
edje_object_signal_emit(o, "e,icon,disabled", "e");
edje_object_message_signal_process(o);
edje_object_part_text_set(o, "e.text.label", label);
edje_object_size_min_calc(o, &mw, &mh);
e_widget_sub_object_add(obj, o);
evas_object_size_hint_min_set(o, mw, mh);
E_FILL(o);
elm_box_pack_end(wd->o_box, o);
evas_object_show(o);
elm_box_recalculate(wd->o_box);
evas_object_size_hint_min_get(wd->o_box, &mw, &mh);
evas_object_resize(wd->o_box, mw, mh);
evas_object_resize(wd->o_base, 500, 500);
e_scrollframe_child_viewport_size_get(wd->o_base, &vw, &vh);
if (wd->scrollable)
e_widget_size_min_set(obj, 500 - vw, mh + (500 - vh));
else
e_widget_size_min_set(obj, mw + (500 - vw), mh + (500 - vh));
evas_object_resize(wd->o_box, mw, mh);
}
E_API void
e_widget_toolbar_item_remove(Evas_Object *obj, int num)
{
E_Widget_Data *wd;
Item *it;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
it = eina_list_nth(wd->items, num);
if (it)
{
evas_object_del(it->o_base);
if (it->o_icon) evas_object_del(it->o_icon);
wd->items = eina_list_remove(wd->items, it);
E_FREE(it);
}
}
E_API void
e_widget_toolbar_item_select(Evas_Object *obj, int num)
{
E_Widget_Data *wd = NULL;
Eina_List *l = NULL;
Item *it = NULL;
int i = 0;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
EINA_LIST_FOREACH(wd->items, l, it)
{
if (i == num)
{
if (!it->selected) _item_select(it);
}
else
{
if (it->selected) _item_unselect(it);
}
i++;
}
}
E_API void
e_widget_toolbar_item_label_set(Evas_Object *obj, int num, const char *label)
{
E_Widget_Data *wd = NULL;
Item *it = NULL;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
it = eina_list_nth(wd->items, num);
if (it)
{
int mw, mh;
edje_object_part_text_set(it->o_base, "e.text.label", label);
edje_object_size_min_calc(it->o_base, &mw, &mh);
evas_object_size_hint_min_set(it->o_base, mw, mh);
}
}
E_API void
e_widget_toolbar_scrollable_set(Evas_Object *obj, Eina_Bool scrollable)
{
E_Widget_Data *wd;
Evas_Coord mw = 0, mh = 0, vw = 0, vh = 0;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
wd->scrollable = scrollable;
elm_box_recalculate(wd->o_box);
evas_object_size_hint_min_get(wd->o_box, &mw, &mh);
evas_object_resize(wd->o_box, mw, mh);
evas_object_resize(wd->o_base, 500, 500);
e_scrollframe_child_viewport_size_get(wd->o_base, &vw, &vh);
if (wd->scrollable)
e_widget_size_min_set(obj, 500 - vw, mh + (500 - vh));
else
e_widget_size_min_set(obj, mw + (500 - vw), mh + (500 - vh));
evas_object_resize(wd->o_box, mw, mh);
}
E_API void
e_widget_toolbar_focus_steal_set(Evas_Object *obj, Eina_Bool steal)
{
E_Widget_Data *wd;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
if (wd->focus_steal == steal) return;
if (steal)
{
evas_object_event_callback_add(e_scrollframe_edje_object_get(wd->o_base),
EVAS_CALLBACK_MOUSE_DOWN,
_e_wid_focus_steal, obj);
wd->focus_steal = EINA_TRUE;
}
else
{
evas_object_event_callback_del(e_scrollframe_edje_object_get(wd->o_base),
EVAS_CALLBACK_MOUSE_DOWN,
_e_wid_focus_steal);
wd->focus_steal = EINA_FALSE;
}
}
E_API void
e_widget_toolbar_clear(Evas_Object *obj)
{
E_Widget_Data *wd = NULL;
Item *it = NULL;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
EINA_LIST_FREE(wd->items, it)
{
evas_object_del(it->o_base);
if (it->o_icon) evas_object_del(it->o_icon);
E_FREE(it);
}
}
E_API int
e_widget_toolbar_item_selected_get(Evas_Object *obj)
{
E_Widget_Data *wd = NULL;
Eina_List *l = NULL;
Item *it = NULL;
int i = 0;
if (!obj) return 0;
if (!(wd = e_widget_data_get(obj))) return 0;
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected) return i;
i++;
}
return 0;
}
/* local functions */
static void
_e_wid_del_hook(Evas_Object *obj)
{
E_Widget_Data *wd;
Item *it;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
EINA_LIST_FREE(wd->items, it)
{
evas_object_del(it->o_base);
if (it->o_icon) evas_object_del(it->o_icon);
E_FREE(it);
}
E_FREE(wd);
}
static void
_e_wid_disable_hook(Evas_Object *obj)
{
E_Widget_Data *wd;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
if (e_widget_disabled_get(obj))
edje_object_signal_emit(e_scrollframe_edje_object_get(wd->o_base),
"e,state,disabled", "e");
else
edje_object_signal_emit(e_scrollframe_edje_object_get(wd->o_base),
"e,state,enabled", "e");
}
static void
_e_wid_signal_cb1(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
Item *it, *it2;
E_Widget_Data *wd;
Eina_List *l;
if (!(it = data)) return;
if (it->selected) return;
wd = e_widget_data_get(it->o_toolbar);
EINA_LIST_FOREACH(wd->items, l, it2)
{
if (it2->selected)
{
_item_unselect(it2);
break;
}
}
_item_select(it);
}
static void
_e_wid_signal_prev(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
E_Widget_Data *wd;
Eina_List *l, *l2;
Item *it = NULL, *it2 = NULL;
if (!(wd = e_widget_data_get(data))) return;
if ((!wd->o_base) || (!wd->o_box)) return;
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected)
{
l2 = eina_list_prev(l);
if (l2) it2 = eina_list_data_get(l2);
break;
}
}
if ((it) && (it2) && (it != it2))
{
_item_unselect(it);
_item_select(it2);
}
}
static void
_e_wid_signal_next(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
{
E_Widget_Data *wd;
Eina_List *l, *l2;
Item *it = NULL, *it2 = NULL;
if (!(wd = e_widget_data_get(data))) return;
if ((!wd->o_base) || (!wd->o_box)) return;
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected)
{
l2 = eina_list_next(l);
if (l2) it2 = eina_list_data_get(l2);
break;
}
}
if ((it) && (it2) && (it != it2))
{
_item_unselect(it);
_item_select(it2);
}
}
static void
_e_wid_cb_scrollframe_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Widget_Data *wd;
Evas_Coord mw, mh, vw, vh, w, h;
Eina_List *l;
Item *it;
if (!(wd = e_widget_data_get(data))) return;
if ((!wd->o_base) || (!wd->o_box)) return;
e_scrollframe_child_viewport_size_get(wd->o_base, &vw, &vh);
elm_box_recalculate(wd->o_box);
evas_object_size_hint_min_get(wd->o_box, &mw, &mh);
evas_object_geometry_get(wd->o_box, NULL, NULL, &w, &h);
if (vw >= mw)
{
if (w != vw) evas_object_resize(wd->o_box, vw, h);
}
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected)
{
_item_show(it);
break;
}
}
}
static void
_e_wid_cb_key_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Key_Down *ev;
E_Widget_Data *wd;
Eina_List *l, *l2;
Item *it = NULL, *it2 = NULL;
ev = event_info;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
wd = e_widget_data_get(data);
if ((!strcmp(ev->key, "Up")) || (!strcmp(ev->key, "KP_Up")) ||
(!strcmp(ev->key, "Left")) || (!strcmp(ev->key, "KP_Left")))
{
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected)
{
l2 = eina_list_prev(l);
if (l2) it2 = eina_list_data_get(l2);
break;
}
}
}
else if ((!strcmp(ev->key, "Down")) ||
(!strcmp(ev->key, "KP_Down")) ||
(!strcmp(ev->key, "Right")) ||
(!strcmp(ev->key, "KP_Right")))
{
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected)
{
l2 = eina_list_next(l);
if (l2) it2 = eina_list_data_get(l2);
break;
}
}
}
else if ((!strcmp(ev->key, "Home")) ||
(!strcmp(ev->key, "KP_Home")))
{
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected)
{
it2 = eina_list_data_get(wd->items);
break;
}
}
}
else if ((!strcmp(ev->key, "End")) || (!strcmp(ev->key, "KP_End")))
{
EINA_LIST_FOREACH(wd->items, l, it)
{
if (it->selected)
{
it2 = eina_list_last_data_get(wd->items);
break;
}
}
}
if ((it) && (it2) && (it != it2))
{
_item_unselect(it);
_item_select(it2);
}
}
static void
_e_wid_focus_hook(Evas_Object *obj)
{
E_Widget_Data *wd;
if (!obj) return;
if (!(wd = e_widget_data_get(obj))) return;
if (e_widget_focus_get(obj))
{
edje_object_signal_emit(e_scrollframe_edje_object_get(wd->o_base), "e,state,focused", "e");
evas_object_focus_set(obj, EINA_TRUE);
}
else
{
edje_object_signal_emit(e_scrollframe_edje_object_get(wd->o_base), "e,state,unfocused", "e");
evas_object_focus_set(obj, EINA_FALSE);
}
}
static void
_e_wid_focus_steal(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
e_widget_focus_steal(data);
}
static void
_item_show(Item *it)
{
E_Widget_Data *wd;
Evas_Coord x, y, w, h, bx, by;
wd = e_widget_data_get(it->o_toolbar);
evas_object_geometry_get(wd->o_box, &bx, &by, NULL, NULL);
evas_object_geometry_get(it->o_base, &x, &y, &w, &h);
e_scrollframe_child_region_show(wd->o_base, x - bx, y - by, w, h);
}
static void
_item_select(Item *it)
{
it->selected = EINA_TRUE;
edje_object_signal_emit(it->o_base, "e,state,selected", "e");
if (it->o_icon)
{
if (strcmp(evas_object_type_get(it->o_icon), "e_icon"))
edje_object_signal_emit(it->o_icon, "e,state,selected", "e");
else
e_icon_selected_set(it->o_icon, EINA_TRUE);
}
_item_show(it);
if (it->func) it->func((void *)it->data1, (void *)it->data2);
}
static void
_item_unselect(Item *it)
{
it->selected = EINA_FALSE;
edje_object_signal_emit(it->o_base, "e,state,unselected", "e");
if (it->o_icon)
{
if (strcmp(evas_object_type_get(it->o_icon), "e_icon"))
edje_object_signal_emit(it->o_icon, "e,state,unselected", "e");
else
e_icon_selected_set(it->o_icon, EINA_FALSE);
}
}