586 lines
16 KiB
C
586 lines
16 KiB
C
#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);
|
|
}
|
|
}
|
|
|