1 #include <Elementary.h>
5 * @defgroup Anchorview Anchorview
7 * This is just like the Anchorblock object, but provides a scroller to hold
8 * the text automatically.
10 * Signals that you can add callbacks for are:
12 * anchor,clicked - achor called was clicked. event_info is anchor info -
13 * Elm_Entry_Anchorview_Info
15 typedef struct _Widget_Data Widget_Data;
16 typedef struct _Elm_Anchorview_Item_Provider Elm_Anchorview_Item_Provider;
20 Evas_Object *scroller, *entry;
21 Evas_Object *hover_parent;
22 Evas_Object *pop, *hover;
23 Eina_List *item_providers;
24 const char *hover_style;
27 struct _Elm_Anchorview_Item_Provider
29 Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item);
33 static const char *widtype = NULL;
35 static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
36 static const Evas_Smart_Cb_Description _signals[] = {
37 {SIG_ANCHOR_CLICKED, ""}, /* TODO: declare the type properly, as data is
43 static void _del_pre_hook(Evas_Object *obj);
44 static void _del_hook(Evas_Object *obj);
45 static void _sizing_eval(Evas_Object *obj);
46 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
47 static void _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
48 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
51 _del_pre_hook(Evas_Object *obj)
53 elm_anchorview_hover_end(obj);
54 elm_anchorview_hover_parent_set(obj, NULL);
58 _del_hook(Evas_Object *obj)
60 Widget_Data *wd = elm_widget_data_get(obj);
61 Elm_Anchorview_Item_Provider *ip;
63 if (wd->hover_style) eina_stringshare_del(wd->hover_style);
64 EINA_LIST_FREE(wd->item_providers, ip)
72 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
74 Widget_Data *wd = elm_widget_data_get(obj);
76 elm_widget_mirrored_set(wd->hover, rtl);
80 _theme_hook(Evas_Object *obj)
82 Widget_Data *wd = elm_widget_data_get(obj);
84 _elm_widget_mirrored_reload(obj);
85 _mirrored_set(obj, elm_widget_mirrored_get(obj));
89 _sizing_eval(Evas_Object *obj)
91 Widget_Data *wd = elm_widget_data_get(obj);
92 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
94 evas_object_size_hint_min_set(obj, minw, minh);
95 evas_object_size_hint_max_set(obj, maxw, maxh);
99 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
105 _hover_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
107 elm_anchorview_hover_end(data);
111 _anchor_clicked(void *data, Evas_Object *obj, void *event_info)
113 Widget_Data *wd = elm_widget_data_get(data);
114 Elm_Entry_Anchor_Info *info = event_info;
115 Evas_Object *hover_parent;
116 Elm_Entry_Anchorview_Info ei;
117 Evas_Coord x, w, y, h, px, py;
119 wd->pop = elm_icon_add(obj);
120 evas_object_move(wd->pop, info->x, info->y);
121 evas_object_resize(wd->pop, info->w, info->h);
122 wd->hover = elm_hover_add(obj);
123 elm_widget_mirrored_set(wd->hover, elm_widget_mirrored_get((Evas_Object *) data));
124 if (wd->hover_style) elm_object_style_set(wd->hover, wd->hover_style);
125 hover_parent = wd->hover_parent;
126 if (!hover_parent) hover_parent = obj;
127 elm_hover_parent_set(wd->hover, hover_parent);
128 elm_hover_target_set(wd->hover, wd->pop);
129 ei.name = info->name;
130 ei.button = info->button;
131 ei.hover = wd->hover;
132 ei.anchor.x = info->x;
133 ei.anchor.y = info->y;
134 ei.anchor.w = info->w;
135 ei.anchor.h = info->h;
136 evas_object_geometry_get(hover_parent, &x, &y, &w, &h);
137 ei.hover_parent.x = x;
138 ei.hover_parent.y = y;
139 ei.hover_parent.w = w;
140 ei.hover_parent.h = h;
141 px = info->x + (info->w / 2);
142 py = info->y + (info->h / 2);
144 if (px < (x + (w / 3))) ei.hover_left = 0;
146 if (px > (x + ((w * 2) / 3))) ei.hover_right = 0;
148 if (py < (y + (h / 3))) ei.hover_top = 0;
150 if (py > (y + ((h * 2) / 3))) ei.hover_bottom = 0;
152 if (elm_widget_mirrored_get(wd->hover))
153 { /* Swap right and left because they switch sides in RTL */
154 Eina_Bool tmp = ei.hover_left;
155 ei.hover_left = ei.hover_right;
156 ei.hover_right = tmp;
159 evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, &ei);
160 evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked, data);
161 evas_object_show(wd->hover);
165 _parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
167 Widget_Data *wd = elm_widget_data_get(data);
169 wd->hover_parent = NULL;
173 _item_provider(void *data, Evas_Object *entry __UNUSED__, const char *item)
175 Widget_Data *wd = elm_widget_data_get(data);
177 Elm_Anchorview_Item_Provider *ip;
179 EINA_LIST_FOREACH(wd->item_providers, l, ip)
183 o = ip->func(ip->data, data, item);
190 * Add a new Anchorview object
192 * @param parent The parent object
193 * @return The new object or NULL if it cannot be created
195 * @ingroup Anchorview
198 elm_anchorview_add(Evas_Object *parent)
204 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
206 ELM_SET_WIDTYPE(widtype, "anchorview");
207 elm_widget_type_set(obj, "anchorview");
208 elm_widget_sub_object_add(parent, obj);
209 elm_widget_data_set(obj, wd);
210 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
211 elm_widget_del_hook_set(obj, _del_hook);
212 elm_widget_theme_hook_set(obj, _theme_hook);
213 elm_widget_can_focus_set(obj, EINA_TRUE);
215 wd->scroller = elm_scroller_add(parent);
216 elm_widget_resize_object_set(obj, wd->scroller);
217 wd->entry = elm_entry_add(parent);
218 elm_entry_item_provider_prepend(wd->entry, _item_provider, obj);
219 elm_entry_editable_set(wd->entry, 0);
220 evas_object_size_hint_weight_set(wd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
221 evas_object_size_hint_align_set(wd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
222 elm_scroller_content_set(wd->scroller, wd->entry);
223 evas_object_show(wd->entry);
225 evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
226 _changed_size_hints, obj);
228 elm_entry_entry_set(wd->entry, "");
230 evas_object_smart_callback_add(wd->entry, "anchor,clicked",
231 _anchor_clicked, obj);
233 _mirrored_set(obj, elm_widget_mirrored_get(obj));
236 // TODO: convert Elementary to subclassing of Evas_Smart_Class
237 // TODO: and save some bytes, making descriptions per-class and not instance!
238 evas_object_smart_callbacks_descriptions_set(obj, _signals);
243 * Set the text markup of the anchorview
245 * This sets the text of the anchorview to be the text given as @p text. This
246 * text is in markup format with \<a href=XXX\> beginning an achor with the
247 * string link of 'XXX', and \</\> or \</a\> ending the link. Other markup can
248 * be used dependign on the style support.
250 * @param obj The anchorview object
251 * @param text The text to set, or NULL to clear
253 * @ingroup Anchorview
256 elm_anchorview_text_set(Evas_Object *obj, const char *text)
258 ELM_CHECK_WIDTYPE(obj, widtype);
259 Widget_Data *wd = elm_widget_data_get(obj);
261 elm_entry_entry_set(wd->entry, text);
262 if (wd->hover) evas_object_del(wd->hover);
263 if (wd->pop) evas_object_del(wd->pop);
270 * Get the markup text set for the anchorview
272 * This retrieves back the string set by @c elm_anchorview_text_set().
274 * @param obj The anchorview object
275 * @return text The markup text set or @c NULL, either if it was not set
276 * or an error occurred
278 * @ingroup Anchorview
281 elm_anchorview_text_get(const Evas_Object *obj)
283 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
284 Widget_Data *wd = elm_widget_data_get(obj);
285 if (!wd) return NULL;
286 return elm_entry_entry_get(wd->entry);
290 * Set the parent of the hover popup
292 * This sets the parent of the hover that anchorview will create. See hover
293 * objects for more information on this.
295 * @param obj The anchorview object
296 * @param parent The parent the hover should use
298 * @ingroup Anchorview
301 elm_anchorview_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
303 ELM_CHECK_WIDTYPE(obj, widtype);
304 Widget_Data *wd = elm_widget_data_get(obj);
306 if (wd->hover_parent)
307 evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
308 wd->hover_parent = parent;
309 if (wd->hover_parent)
310 evas_object_event_callback_add(wd->hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
314 * Get the parent of the hover popup
316 * This gets the parent of the hover that anchorview will created. See hover
317 * objects for more information on this.
319 * @param obj The anchorview object
320 * @return The parent used by hover
322 * @ingroup Anchorview
325 elm_anchorview_hover_parent_get(const Evas_Object *obj)
327 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
328 Widget_Data *wd = elm_widget_data_get(obj);
329 if (!wd) return NULL;
330 return wd->hover_parent;
334 * Set the style that the hover should use
336 * This sets the style for the hover that anchorview will create. See hover
337 * objects for more information
339 * @param obj The anchorview object
340 * @param style The style to use
342 * @ingroup Anchorview
345 elm_anchorview_hover_style_set(Evas_Object *obj, const char *style)
347 ELM_CHECK_WIDTYPE(obj, widtype);
348 Widget_Data *wd = elm_widget_data_get(obj);
350 eina_stringshare_replace(&wd->hover_style, style);
354 * Get the style that the hover should use
356 * This gets the style for the hover that anchorview will create. See hover
357 * objects for more information
359 * @param obj The anchorview object
360 * @return The style defined
362 * @ingroup Anchorview
365 elm_anchorview_hover_style_get(const Evas_Object *obj)
367 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
368 Widget_Data *wd = elm_widget_data_get(obj);
369 if (!wd) return NULL;
370 return wd->hover_style;
374 * Stop the hover popup in the anchorview
376 * This will stop the hover popup in the anchorview if it is currently active.
378 * @param obj The anchorview object
380 * @ingroup Anchorview
383 elm_anchorview_hover_end(Evas_Object *obj)
385 ELM_CHECK_WIDTYPE(obj, widtype);
386 Widget_Data *wd = elm_widget_data_get(obj);
388 if (wd->hover) evas_object_del(wd->hover);
389 if (wd->pop) evas_object_del(wd->pop);
397 * This will enable or disable the scroller bounce mode for the anchorview. See
398 * elm_scroller_bounce_set() for details
400 * @param obj The anchorview anchorview
401 * @param h_bounce Allow bounce horizontally
402 * @param v_bounce Allow bounce vertically
404 * @ingroup Anchorview
407 elm_anchorview_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
409 ELM_CHECK_WIDTYPE(obj, widtype);
410 Widget_Data *wd = elm_widget_data_get(obj);
412 elm_scroller_bounce_set(wd->scroller, h_bounce, v_bounce);
416 * Get the bounce mode
418 * @param obj The Anchorview object
419 * @param h_bounce Allow bounce horizontally
420 * @param v_bounce Allow bounce vertically
422 * @ingroup Anchorview
425 elm_anchorview_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
427 ELM_CHECK_WIDTYPE(obj, widtype);
428 Widget_Data *wd = elm_widget_data_get(obj);
430 elm_scroller_bounce_get(wd->scroller, h_bounce, v_bounce);
434 * This appends a custom item provider to the list for that anchorview
436 * This appends the given callback. The list is walked from beginning to end
437 * with each function called given the item href string in the text. If the
438 * function returns an object handle other than NULL (it should create an
439 * and object to do this), then this object is used to replace that item. If
440 * not the next provider is called until one provides an item object, or the
441 * default provider in anchorview does.
443 * @param obj The anchorview object
444 * @param func The function called to provide the item object
445 * @param data The data passed to @p func
447 * @ingroup Anchorview
450 elm_anchorview_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data)
452 ELM_CHECK_WIDTYPE(obj, widtype);
453 Widget_Data *wd = elm_widget_data_get(obj);
455 EINA_SAFETY_ON_NULL_RETURN(func);
456 Elm_Anchorview_Item_Provider *ip = calloc(1, sizeof(Elm_Anchorview_Item_Provider));
460 wd->item_providers = eina_list_append(wd->item_providers, ip);
464 * This prepends a custom item provider to the list for that anchorview
466 * This prepends the given callback. See elm_anchorview_item_provider_append() for
469 * @param obj The anchorview object
470 * @param func The function called to provide the item object
471 * @param data The data passed to @p func
473 * @ingroup Anchorview
476 elm_anchorview_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data)
478 ELM_CHECK_WIDTYPE(obj, widtype);
479 Widget_Data *wd = elm_widget_data_get(obj);
481 EINA_SAFETY_ON_NULL_RETURN(func);
482 Elm_Anchorview_Item_Provider *ip = calloc(1, sizeof(Elm_Anchorview_Item_Provider));
486 wd->item_providers = eina_list_prepend(wd->item_providers, ip);
490 * This removes a custom item provider to the list for that anchorview
492 * This removes the given callback. See elm_anchorview_item_provider_append() for
495 * @param obj The anchorview object
496 * @param func The function called to provide the item object
497 * @param data The data passed to @p func
499 * @ingroup Anchorview
502 elm_anchorview_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *anchorview, const char *item), void *data)
504 ELM_CHECK_WIDTYPE(obj, widtype);
505 Widget_Data *wd = elm_widget_data_get(obj);
507 Elm_Anchorview_Item_Provider *ip;
509 EINA_SAFETY_ON_NULL_RETURN(func);
510 EINA_LIST_FOREACH(wd->item_providers, l, ip)
512 if ((ip->func == func) && (ip->data == data))
514 wd->item_providers = eina_list_remove_list(wd->item_providers, l);