efl/src/lib/elementary/efl_ui_widget_common.c

175 lines
4.0 KiB
C

#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_ACCESS_OBJECT_PROTECTED
#define EFL_ACCESS_COMPONENT_PROTECTED
#define ELM_WIDGET_PROTECTED
#define ELM_WIDGET_ITEM_PROTECTED
#define EFL_INPUT_EVENT_PROTECTED
#define EFL_UI_L10N_PROTECTED
#define EFL_UI_FOCUS_OBJECT_PROTECTED
#define EFL_UI_WIDGET_PART_BG_PROTECTED
#define EFL_PART_PROTECTED
#include <Elementary.h>
#include "elm_priv.h"
#include "elm_widget_container.h"
#include "elm_interface_scrollable.h"
#include "elm_pan_eo.h"
#include "elm_part_helper.h"
#include "elm_widget_combobox.h"
typedef struct {
Eina_Iterator iterator;
Efl_Ui_Widget *origin; //where we started
Efl_Ui_Widget *current; // the current widget where the iterator is
} Widget_Iterator;
static Widget_Iterator*
iter_init(Efl_Ui_Widget *origin)
{
Widget_Iterator *it;
it = calloc(1, sizeof(Widget_Iterator));
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
it->origin = origin;
it->iterator.version = EINA_ITERATOR_VERSION;
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(NULL);
it->iterator.free = FUNC_ITERATOR_FREE(free);
return it;
}
static Efl_Ui_Widget*
_fetch_parent_widget(Efl_Gfx_Entity* o)
{
Efl_Ui_Widget *parent;
if (efl_isa(o, EFL_UI_WIDGET_CLASS))
parent = efl_ui_widget_parent_get(o);
else
parent = evas_object_data_get(o, "elm-parent");
return parent;
}
static Efl_Ui_Widget*
_next_widget(Efl_Gfx_Entity* o)
{
Efl_Ui_Widget *parent;
Eina_List *rel;
parent = _fetch_parent_widget(o);
ELM_WIDGET_DATA_GET_OR_RETURN(parent, pd, NULL);
rel = eina_list_data_find_list(pd->subobjs, o);
return eina_list_data_get(eina_list_next(rel));
}
static Eina_Bool
_widget_next(Widget_Iterator *it, void **data)
{
Efl_Ui_Widget *runner;
Efl_Ui_Widget_Data *pd = NULL;
//Init case
if (!it->current)
{
it->current = it->origin;
goto deliver;
}
if (efl_isa(it->current, EFL_UI_WIDGET_CLASS))
{
pd = efl_data_scope_safe_get(it->current, EFL_UI_WIDGET_CLASS);
EINA_SAFETY_ON_NULL_RETURN_VAL(pd, EINA_FALSE);
}
//If there is a child, go there
if (pd && pd->subobjs)
{
it->current = eina_list_data_get(pd->subobjs);
goto deliver;
}
//If there is no child, then iterate up the parents until we find a widget with a next widget
runner = it->current;
do
{
Efl_Ui_Widget *tmp = _next_widget(runner);
if (tmp)
{
it->current = tmp;
goto deliver;
}
runner = _fetch_parent_widget(runner);
}
while(runner && runner != it->origin);
//Reaching this point here means that there is no widget left, as there is no more parent we can explore
it->current = NULL;
deliver:
*data = (void*)it->current;
return !!it->current;
}
EAPI Eina_Iterator*
efl_ui_widget_tree_iterator(Efl_Ui_Widget *obj)
{
ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
Widget_Iterator *it = iter_init(obj);
it->iterator.next = FUNC_ITERATOR_NEXT(_widget_next);
return &it->iterator;
}
static Eina_Bool
_only_widget(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
{
return efl_isa(data, EFL_UI_WIDGET_CLASS);
}
EAPI Eina_Iterator*
efl_ui_widget_tree_widget_iterator(Efl_Ui_Widget *obj)
{
ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
Eina_Iterator *tree_iterator = efl_ui_widget_tree_iterator(obj);
return eina_iterator_filter_new(tree_iterator, _only_widget, NULL, NULL);
}
static Eina_Bool
_parent_next(Widget_Iterator *it, void **data)
{
if (!it->current)
{
*data = it->origin;
it->current = *data;
}
else
{
Efl_Ui_Widget *parent = efl_ui_widget_parent_get(it->current);
*data = parent;
it->current = parent;
}
return !!*data;
}
EAPI Eina_Iterator*
efl_ui_widget_parent_iterator(Efl_Ui_Widget *obj)
{
ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
Widget_Iterator *it = iter_init(obj);
it->iterator.next = FUNC_ITERATOR_NEXT(_parent_next);
return &it->iterator;
}