Bring focused object into the visible area

There's still a little bugger that can be noticed with the Scroller 2 test
and elm_conform still needs to handle this as scroller does.


SVN revision: 53778
This commit is contained in:
Iván Briano 2010-10-22 18:29:51 +00:00
parent f05ae82f73
commit 3ec77727cc
6 changed files with 144 additions and 0 deletions

View File

@ -196,6 +196,13 @@ _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *so
func_cb);
}
static void
_on_focus_region_hook(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
{
Widget_Data *wd = elm_widget_data_get(obj);
elm_widget_focus_region_get(wd->entry, x, y, w, h);
}
static void
_entry_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
{
@ -357,6 +364,7 @@ elm_scrolled_entry_add(Evas_Object *parent)
elm_widget_disable_hook_set(obj, _disable_hook);
elm_widget_can_focus_set(obj, EINA_TRUE);
elm_widget_theme_hook_set(obj, _theme_hook);
elm_widget_on_focus_region_hook_set(obj, _on_focus_region_hook);
elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);

View File

@ -401,6 +401,13 @@ _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *so
return edje_object_signal_callback_del(wd->ent, emission, source, func_cb);
}
static void
_on_focus_region_hook(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
{
Widget_Data *wd = elm_widget_data_get(obj);
edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
}
static void
_hoversel_position(Evas_Object *obj)
{
@ -1382,6 +1389,7 @@ elm_entry_add(Evas_Object *parent)
elm_widget_theme_hook_set(obj, _theme_hook);
elm_widget_disable_hook_set(obj, _disable_hook);
elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
elm_widget_on_focus_region_hook_set(obj, _on_focus_region_hook);
elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
elm_object_cursor_set(obj, ELM_CURSOR_XTERM);

View File

@ -136,6 +136,7 @@ void _elm_module_del(Elm_Module *m);
const void *_elm_module_symbol_get(Elm_Module *m, const char *name);
void _elm_widget_type_clear(void);
void _elm_widget_focus_region_show(const Evas_Object *obj);
void _elm_unneed_ethumb(void);

View File

@ -256,6 +256,14 @@ _show_region_hook(void *data, Evas_Object *obj)
elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
}
static void
_focus_region_hook(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
{
Widget_Data *wd = elm_widget_data_get(obj);
if (wd->scr)
elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
}
static void
_sizing_eval(Evas_Object *obj)
{
@ -449,6 +457,7 @@ elm_scroller_add(Evas_Object *parent)
elm_widget_focus_next_hook_set(obj, _elm_scroller_focus_next_hook);
elm_widget_can_focus_set(obj, EINA_TRUE);
elm_widget_event_hook_set(obj, _event_hook);
elm_widget_focus_region_hook_set(obj, _focus_region_hook);
wd->widget_name = eina_stringshare_add("scroller");
wd->widget_base = eina_stringshare_add("base");

View File

@ -48,6 +48,8 @@ struct _Smart_Data
void *on_change_data;
void (*on_show_region_func) (void *data, Evas_Object *obj);
void *on_show_region_data;
void (*focus_region_func) (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
void (*on_focus_region_func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
void *data;
Evas_Coord rx, ry, rw, rh;
int scroll_hold;
@ -265,6 +267,8 @@ _parent_focus(Evas_Object *obj)
if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
if (sd->focus_func) sd->focus_func(obj);
_elm_widget_focus_region_show(obj);
sd->focus_order_on_calc = EINA_FALSE;
}
@ -289,6 +293,41 @@ _elm_widget_type_clear(void)
}
}
void
_elm_widget_focus_region_show(const Evas_Object *obj)
{
Evas_Coord x, y, w, h, ox, oy;
Smart_Data *sd2;
Evas_Object *o;
API_ENTRY return;
o = elm_widget_parent_get(obj);
if (!o) return;
elm_widget_focus_region_get(obj, &x, &y, &w, &h);
evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
while (o)
{
Evas_Coord px, py;
sd2 = evas_object_smart_data_get(o);
if (sd2->focus_region_func)
{
sd2->focus_region_func(o, x, y, w, h);
elm_widget_focus_region_get(o, &x, &y, &w, &h);
}
else
{
evas_object_geometry_get(o, &px, &py, NULL, NULL);
x += ox - px;
y += oy - py;
ox = px;
oy = py;
}
o = elm_widget_parent_get(o);
}
}
/**
* @defgroup Widget Widget
*
@ -451,6 +490,46 @@ elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func) (void *data, E
sd->on_show_region_data = data;
}
/**
* Set the hook to use to show the focused region.
*
* Whenever a new widget gets focused or it's needed to show the focused
* area of the current one, this hook will be called on objects that may
* want to move their children into their visible area.
* The area given in the hook function is relative to the @p obj widget.
*
* @param obj The widget object
* @param func The function to call to show the specified area.
*
* @ingroup Widget
*/
EAPI void
elm_widget_focus_region_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h))
{
API_ENTRY return;
sd->focus_region_func = func;
}
/**
* Set the hook to retrieve the focused region of a widget.
*
* This hook will be called by elm_widget_focus_region_get() whenever
* it's needed to get the focused area of a widget. The area must be relative
* to the widget itself and if no hook is set, it will default to the entire
* object.
*
* @param obj The widget object
* @param func The function used to retrieve the focus region.
*
* @ingroup Widget
*/
EAPI void
elm_widget_on_focus_region_hook_set(Evas_Object *obj, void (*func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h))
{
API_ENTRY return;
sd->on_focus_region_func = func;
}
EAPI void
elm_widget_data_set(Evas_Object *obj, void *data)
{
@ -1513,6 +1592,42 @@ elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y,
if (h) *h = sd->rh;
}
/**
* Get the focus region of the given widget.
*
* The focus region is the area of a widget that should brought into the
* visible area when the widget is focused. Mostly used to show the part of
* an entry where the cursor is, for example. The area returned is relative
* to the object @p obj.
* If the @p obj doesn't have the proper on_focus_region_hook set, this
* function will return the full size of the object.
*
* @param obj The widget object
* @param x Where to store the x coordinate of the area
* @param y Where to store the y coordinate of the area
* @param w Where to store the width of the area
* @param h Where to store the height of the area
*
* @ingroup Widget
*/
EAPI void
elm_widget_focus_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
{
Smart_Data *sd;
if (!obj) return;
sd = evas_object_smart_data_get(obj);
if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
{
evas_object_geometry_get(obj, NULL, NULL, w, h);
if (x) *x = 0;
if (y) *y = 0;
return;
}
sd->on_focus_region_func(obj, x, y, w, h);
}
EAPI void
elm_widget_scroll_hold_push(Evas_Object *obj)
{

View File

@ -223,6 +223,8 @@ EAPI void elm_widget_focus_next_hook_set(Evas_Object *obj, Eina_Bool
EAPI void elm_widget_on_focus_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
EAPI void elm_widget_on_change_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
EAPI void elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func) (void *data, Evas_Object *obj), void *data);
EAPI void elm_widget_focus_region_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h));
EAPI void elm_widget_on_focus_region_hook_set(Evas_Object *obj, void (*func) (const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h));
EAPI void elm_widget_data_set(Evas_Object *obj, void *data);
EAPI void *elm_widget_data_get(const Evas_Object *obj);
EAPI void elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj);
@ -265,6 +267,7 @@ EAPI void elm_widget_disabled_set(Evas_Object *obj, int disabled);
EAPI int elm_widget_disabled_get(const Evas_Object *obj);
EAPI void elm_widget_show_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
EAPI void elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
EAPI void elm_widget_focus_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
EAPI void elm_widget_scroll_hold_push(Evas_Object *obj);
EAPI void elm_widget_scroll_hold_pop(Evas_Object *obj);
EAPI int elm_widget_scroll_hold_get(const Evas_Object *obj);