added elm_bg_load_size_set
[framework/uifw/elementary.git] / src / lib / elm_bg.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Bg Bg
6  * @ingroup Elementary
7  *
8  * The bg object is used for setting a solid background to a window or packing
9  * into any container object.
10  */
11
12 typedef struct _Widget_Data Widget_Data;
13
14 struct _Widget_Data
15 {
16    Evas_Object *base, *rect, *img, *overlay;
17    const char  *file, *group;
18    Elm_Bg_Option option;
19    struct {
20       Evas_Coord w, h;
21    } load_opts;
22 };
23
24 static const char *widtype = NULL;
25
26 static void _del_hook(Evas_Object *obj);
27 static void _theme_hook(Evas_Object *obj);
28 static void _custom_resize(void *data, Evas *a, Evas_Object *obj, void *event_info);
29
30 static void
31 _del_hook(Evas_Object *obj)
32 {
33    Widget_Data *wd = elm_widget_data_get(obj);
34    free(wd);
35 }
36
37 static void
38 _theme_hook(Evas_Object *obj)
39 {
40    Widget_Data *wd = elm_widget_data_get(obj);
41    Evas_Coord w, h;
42
43    _elm_theme_object_set(obj, wd->base, "bg", "base", 
44                          elm_widget_style_get(obj));
45
46    if (wd->rect)
47      edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
48    if (wd->img)
49      edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
50    if (wd->overlay)
51      edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
52
53 // FIXME: if i don't do this, bg doesnt calc correctly. why?   
54    evas_object_geometry_get(wd->base, NULL, NULL, &w, &h);
55    evas_object_resize(wd->base, w, h);
56 }
57
58 static void
59 _custom_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
60 {
61    Widget_Data *wd = data;
62    Evas_Coord bx = 0, by = 0, bw = 0, bh = 0;
63    Evas_Coord iw = 0, ih = 0, mw = -1, mh = -1;
64    Evas_Coord fx = 0, fy = 0, fw = 0, fh = 0;
65    Evas_Coord nx = 0, ny = 0, nw = 0, nh = 0;
66    const char *p;
67
68    if ((!wd->img) || (!wd->file)) return;
69    if (((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))) return;
70
71    /* grab image size */
72    evas_object_image_size_get(wd->img, &iw, &ih);
73    if ((iw < 1) || (ih < 1)) return;
74
75    /* grab base object dimensions */
76    evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
77
78    /* set some defaults */
79    nx = bx;
80    ny = by;
81    nw = bw;
82    nh = bh;
83
84    switch (wd->option) 
85      {
86       case ELM_BG_OPTION_CENTER:
87         fw = nw = iw;
88         fh = nh = ih;
89         nx = ((bw - fw) / 2);
90         ny = ((bh - fh) / 2);
91         mw = iw;
92         mh = ih;
93         break;
94       case ELM_BG_OPTION_SCALE:
95         fw = bw;
96         fh = ((ih * fw) / iw);
97         if (fh < bh)
98           {
99              fh = bh;
100              fw = ((iw * fh) / ih);
101           }
102         fx = ((bw - fw) / 2);
103         fy = ((bh - fh) / 2);
104         break;
105       case ELM_BG_OPTION_TILE:
106         fw = iw;
107         fh = ih;
108         break;
109       case ELM_BG_OPTION_STRETCH:
110       default:
111         fw = bw;
112         fh = bh;
113         break;
114      }
115
116    evas_object_move(wd->img, nx, ny);
117    evas_object_resize(wd->img, nw, nh);
118    evas_object_image_fill_set(wd->img, fx, fy, fw, fh);
119
120    evas_object_size_hint_min_set(wd->img, mw, mh);
121    evas_object_size_hint_max_set(wd->img, mw, mh);
122 }
123
124 /**
125  * Add a new background to the parent
126  *
127  * @param parent The parent object
128  * @return The new object or NULL if it cannot be created
129  *
130  * @ingroup Bg
131  */
132 EAPI Evas_Object *
133 elm_bg_add(Evas_Object *parent)
134 {
135    Evas_Object *obj;
136    Evas *e;
137    Widget_Data *wd;
138
139    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
140
141    wd = ELM_NEW(Widget_Data);
142    e = evas_object_evas_get(parent);
143    if (!e) return NULL;
144    obj = elm_widget_add(e);
145    ELM_SET_WIDTYPE(widtype, "bg");
146    elm_widget_type_set(obj, "bg");
147    elm_widget_sub_object_add(parent, obj);
148    elm_widget_data_set(obj, wd);
149    elm_widget_del_hook_set(obj, _del_hook);
150    elm_widget_theme_hook_set(obj, _theme_hook);
151    elm_widget_can_focus_set(obj, EINA_FALSE);
152
153    wd->base = edje_object_add(e);
154    _elm_theme_object_set(obj, wd->base, "bg", "base", "default");
155    elm_widget_resize_object_set(obj, wd->base);
156
157    evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE, 
158                                   _custom_resize, wd);
159
160    wd->option = ELM_BG_OPTION_SCALE;
161    return obj;
162 }
163
164 /**
165  * Set the file (image or edje) used for the background
166  *
167  * @param obj The bg object
168  * @param file The file path
169  * @param group Optional key (group in Edje) within the file
170  *
171  * This sets the image file used in the background object. The image (or edje)
172  * will be stretched (retaining aspect if its an image file) to completely fill
173  * the bg object. This may mean some parts are not visible.
174  *
175  * @note  Once the image of @p obj is set, a previously set one will be deleted,
176  * even if @p file is NULL.
177  *
178  * @ingroup Bg
179  */
180 EAPI void
181 elm_bg_file_set(Evas_Object *obj, const char *file, const char *group)
182 {
183    ELM_CHECK_WIDTYPE(obj, widtype);
184    Widget_Data *wd = elm_widget_data_get(obj);
185    const char *p;
186
187    if (wd->img)
188      {
189         evas_object_del(wd->img);
190         wd->img = NULL;
191      }
192    if (!file)
193      {
194         eina_stringshare_del(wd->file);
195         wd->file = NULL;
196         eina_stringshare_del(wd->group);
197         wd->group = NULL;
198         return;
199      }
200    eina_stringshare_replace(&wd->file, file);
201    eina_stringshare_replace(&wd->group, group);
202    if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
203      {
204         wd->img = edje_object_add(evas_object_evas_get(wd->base));
205         edje_object_file_set(wd->img, file, group);
206      }
207    else
208      {
209         wd->img = evas_object_image_add(evas_object_evas_get(wd->base));
210         if ((wd->load_opts.w > 0) && (wd->load_opts.h > 0))
211            evas_object_image_load_size_set(wd->img, wd->load_opts.w, wd->load_opts.h);
212         evas_object_image_file_set(wd->img, file, group);
213      }
214    evas_object_repeat_events_set(wd->img, EINA_TRUE);
215    edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
216    elm_widget_sub_object_add(obj, wd->img);
217    _custom_resize(wd, NULL, NULL, NULL);
218 }
219
220 /**
221  * Get the file (image or edje) used for the background
222  *
223  * @param obj The bg object
224  * @param file The file path
225  * @param group Optional key (group in Edje) within the file
226  *
227  * @ingroup Bg
228  */
229 EAPI void
230 elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group)
231 {
232    ELM_CHECK_WIDTYPE(obj, widtype);
233    Widget_Data *wd = elm_widget_data_get(obj);
234    if (file) *file = wd->file;
235    if (group) *group = wd->group;
236 }
237
238 /**
239  * Set the option used for the background image
240  *
241  * @param obj The bg object
242  * @param option The desired background option (TILE, SCALE)
243  *
244  * This sets the option used for manipulating the display of the background 
245  * image. The image can be tiled or scaled.
246  *
247  * @ingroup Bg
248  */
249 EAPI void 
250 elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option) 
251 {
252    ELM_CHECK_WIDTYPE(obj, widtype);
253    Widget_Data *wd;
254
255    wd = elm_widget_data_get(obj);
256    wd->option = option;
257    _custom_resize(wd, NULL, NULL, NULL);
258 }
259
260 /**
261  * Get the option used for the background image
262  *
263  * @param obj The bg object
264  * @return The desired background option (TILE, SCALE)
265  *
266  * @ingroup Bg
267  */
268 EAPI Elm_Bg_Option
269 elm_bg_option_get(const Evas_Object *obj)
270 {
271    ELM_CHECK_WIDTYPE(obj, widtype) 0;
272    Widget_Data *wd;
273
274    wd = elm_widget_data_get(obj);
275    return wd->option;
276 }
277
278 /**
279  * Set the option used for the background color
280  *
281  * @param obj The bg object
282  * @param r
283  * @param g
284  * @param b
285  *
286  * This sets the color used for the background rectangle.
287  *
288  * @ingroup Bg
289  */
290 EAPI void 
291 elm_bg_color_set(Evas_Object *obj, int r, int g, int b) 
292 {
293    ELM_CHECK_WIDTYPE(obj, widtype);
294    Widget_Data *wd;
295
296    wd = elm_widget_data_get(obj);
297    if (!wd->rect)
298      {
299         wd->rect = evas_object_rectangle_add(evas_object_evas_get(wd->base));
300         edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
301         elm_widget_sub_object_add(obj, wd->rect);
302         _custom_resize(wd, NULL, NULL, NULL);
303      }
304    evas_object_color_set(wd->rect, r, g, b, 255);
305 }
306
307 /**
308  * Get the option used for the background color
309  *
310  * @param obj The bg object
311  * @param r
312  * @param g
313  * @param b
314  *
315  * @ingroup Bg
316  */
317 EAPI void
318 elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b)
319 {
320    ELM_CHECK_WIDTYPE(obj, widtype);
321    Widget_Data *wd;
322
323    wd = elm_widget_data_get(obj);
324    evas_object_color_get(wd->rect, r, g, b, NULL);
325 }
326
327 /**
328  * Set the overlay object used for the background object.
329  *
330  * @param obj The bg object
331  * @param overlay The overlay object
332  *
333  * This provides a way for elm_bg to have an 'overlay' (such as animated fog)
334  * Once the over object is set, a previously set one will be deleted.
335  * If you want to keep that old content object, use the
336  * elm_bg_overlay_unset() function.
337  *
338  * @ingroup Bg
339  */
340 EAPI void
341 elm_bg_overlay_set(Evas_Object *obj, Evas_Object *overlay)
342 {
343    ELM_CHECK_WIDTYPE(obj, widtype);
344    Widget_Data *wd = elm_widget_data_get(obj);
345    if (!wd) return;
346    if (wd->overlay)
347      {
348         evas_object_del(wd->overlay);
349         wd->overlay = NULL;
350      }
351    if (overlay)
352      {
353         wd->overlay = overlay;
354         edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
355         elm_widget_sub_object_add(obj, wd->overlay);
356      }
357
358    _custom_resize(wd, NULL, NULL, NULL);
359 }
360
361 /**
362  * Set the overlay object used for the background object.
363  *
364  * @param obj The bg object
365  * @return The content that is being used
366  *
367  * Return the content object which is set for this widget
368  *
369  * @ingroup Bg
370  */
371 EAPI Evas_Object *
372 elm_bg_overlay_get(const Evas_Object *obj)
373 {
374    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
375    Widget_Data *wd = elm_widget_data_get(obj);
376    if (!wd) return NULL;
377    return wd->overlay;
378 }
379
380 /**
381  * Get the overlay object used for the background object.
382  *
383  * @param obj The bg object
384  * @return The content that was being used
385  *
386  * Unparent and return the overlay object which was set for this widget
387  *
388  * @ingroup Bg
389  */
390 EAPI Evas_Object *
391 elm_bg_overlay_unset(Evas_Object *obj)
392 {
393    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
394    Widget_Data *wd = elm_widget_data_get(obj);
395    Evas_Object *overlay;
396    if (!wd) return NULL;
397    if (!wd->overlay) return NULL;
398    overlay = wd->overlay;
399    elm_widget_sub_object_del(obj, wd->overlay);
400    edje_object_part_unswallow(wd->base, wd->overlay);
401    wd->overlay = NULL;
402    _custom_resize(wd, NULL, NULL, NULL);
403    return overlay;
404 }
405
406 /**
407  * Set the size of a loaded image of the canvas of the bg.
408  *
409  * @param obj The bg object
410  * @param w The new width of the canvas image given.
411  * @param h The new height of the canvas image given.
412  *
413  * This function sets a new size for the canvas image of the given the bg.
414  *
415  */
416 EAPI void
417 elm_bg_load_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
418 {
419    ELM_CHECK_WIDTYPE(obj, widtype);
420    Widget_Data *wd = elm_widget_data_get(obj);
421    const char *p;
422    if (!wd) return;
423    wd->load_opts.w = w;
424    wd->load_opts.h = h;
425    if (!wd->img) return;
426    if (!(((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))))
427       evas_object_image_load_size_set(wd->img, w, h);
428 }
429