Elementary migration around 2011/04/06
[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    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
140
141    ELM_SET_WIDTYPE(widtype, "bg");
142    elm_widget_type_set(obj, "bg");
143    elm_widget_sub_object_add(parent, obj);
144    elm_widget_data_set(obj, wd);
145    elm_widget_del_hook_set(obj, _del_hook);
146    elm_widget_theme_hook_set(obj, _theme_hook);
147    elm_widget_can_focus_set(obj, EINA_FALSE);
148
149    wd->base = edje_object_add(e);
150    _elm_theme_object_set(obj, wd->base, "bg", "base", "default");
151    elm_widget_resize_object_set(obj, wd->base);
152
153    evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE,
154                                   _custom_resize, wd);
155
156    wd->option = ELM_BG_OPTION_SCALE;
157    return obj;
158 }
159
160 /**
161  * Set the file (image or edje) used for the background
162  *
163  * @param obj The bg object
164  * @param file The file path
165  * @param group Optional key (group in Edje) within the file
166  *
167  * This sets the image file used in the background object. The image (or edje)
168  * will be stretched (retaining aspect if its an image file) to completely fill
169  * the bg object. This may mean some parts are not visible.
170  *
171  * @note  Once the image of @p obj is set, a previously set one will be deleted,
172  * even if @p file is NULL.
173  *
174  * @ingroup Bg
175  */
176 EAPI void
177 elm_bg_file_set(Evas_Object *obj, const char *file, const char *group)
178 {
179    ELM_CHECK_WIDTYPE(obj, widtype);
180    Widget_Data *wd = elm_widget_data_get(obj);
181    const char *p;
182
183    if (wd->img)
184      {
185         evas_object_del(wd->img);
186         wd->img = NULL;
187      }
188    if (!file)
189      {
190         eina_stringshare_del(wd->file);
191         wd->file = NULL;
192         eina_stringshare_del(wd->group);
193         wd->group = NULL;
194         return;
195      }
196    eina_stringshare_replace(&wd->file, file);
197    eina_stringshare_replace(&wd->group, group);
198    if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
199      {
200         wd->img = edje_object_add(evas_object_evas_get(wd->base));
201         edje_object_file_set(wd->img, file, group);
202      }
203    else
204      {
205         wd->img = evas_object_image_add(evas_object_evas_get(wd->base));
206         if ((wd->load_opts.w > 0) && (wd->load_opts.h > 0))
207           evas_object_image_load_size_set(wd->img, wd->load_opts.w, wd->load_opts.h);
208         evas_object_image_file_set(wd->img, file, group);
209      }
210    evas_object_repeat_events_set(wd->img, EINA_TRUE);
211    edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
212    elm_widget_sub_object_add(obj, wd->img);
213    _custom_resize(wd, NULL, NULL, NULL);
214 }
215
216 /**
217  * Get the file (image or edje) used for the background
218  *
219  * @param obj The bg object
220  * @param file The file path
221  * @param group Optional key (group in Edje) within the file
222  *
223  * @ingroup Bg
224  */
225 EAPI void
226 elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group)
227 {
228    ELM_CHECK_WIDTYPE(obj, widtype);
229    Widget_Data *wd = elm_widget_data_get(obj);
230    if (file) *file = wd->file;
231    if (group) *group = wd->group;
232 }
233
234 /**
235  * Set the option used for the background image
236  *
237  * @param obj The bg object
238  * @param option The desired background option (TILE, SCALE)
239  *
240  * This sets the option used for manipulating the display of the background 
241  * image. The image can be tiled or scaled.
242  *
243  * @ingroup Bg
244  */
245 EAPI void
246 elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option)
247 {
248    ELM_CHECK_WIDTYPE(obj, widtype);
249    Widget_Data *wd;
250
251    wd = elm_widget_data_get(obj);
252    wd->option = option;
253    _custom_resize(wd, NULL, NULL, NULL);
254 }
255
256 /**
257  * Get the option used for the background image
258  *
259  * @param obj The bg object
260  * @return The desired background option (TILE, SCALE)
261  *
262  * @ingroup Bg
263  */
264 EAPI Elm_Bg_Option
265 elm_bg_option_get(const Evas_Object *obj)
266 {
267    ELM_CHECK_WIDTYPE(obj, widtype) 0;
268    Widget_Data *wd;
269
270    wd = elm_widget_data_get(obj);
271    return wd->option;
272 }
273
274 /**
275  * Set the option used for the background color
276  *
277  * @param obj The bg object
278  * @param r
279  * @param g
280  * @param b
281  *
282  * This sets the color used for the background rectangle.
283  *
284  * @ingroup Bg
285  */
286 EAPI void
287 elm_bg_color_set(Evas_Object *obj, int r, int g, int b)
288 {
289    ELM_CHECK_WIDTYPE(obj, widtype);
290    Widget_Data *wd;
291
292    wd = elm_widget_data_get(obj);
293    if (!wd->rect)
294      {
295         wd->rect = evas_object_rectangle_add(evas_object_evas_get(wd->base));
296         edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
297         elm_widget_sub_object_add(obj, wd->rect);
298         _custom_resize(wd, NULL, NULL, NULL);
299      }
300    evas_object_color_set(wd->rect, r, g, b, 255);
301 }
302
303 /**
304  * Get the option used for the background color
305  *
306  * @param obj The bg object
307  * @param r
308  * @param g
309  * @param b
310  *
311  * @ingroup Bg
312  */
313 EAPI void
314 elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b)
315 {
316    ELM_CHECK_WIDTYPE(obj, widtype);
317    Widget_Data *wd;
318
319    wd = elm_widget_data_get(obj);
320    evas_object_color_get(wd->rect, r, g, b, NULL);
321 }
322
323 /**
324  * Set the overlay object used for the background object.
325  *
326  * @param obj The bg object
327  * @param overlay The overlay object
328  *
329  * This provides a way for elm_bg to have an 'overlay' (such as animated fog)
330  * Once the over object is set, a previously set one will be deleted.
331  * If you want to keep that old content object, use the
332  * elm_bg_overlay_unset() function.
333  *
334  * @ingroup Bg
335  */
336 EAPI void
337 elm_bg_overlay_set(Evas_Object *obj, Evas_Object *overlay)
338 {
339    ELM_CHECK_WIDTYPE(obj, widtype);
340    Widget_Data *wd = elm_widget_data_get(obj);
341    if (!wd) return;
342    if (wd->overlay)
343      {
344         evas_object_del(wd->overlay);
345         wd->overlay = NULL;
346      }
347    if (overlay)
348      {
349         wd->overlay = overlay;
350         edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
351         elm_widget_sub_object_add(obj, wd->overlay);
352      }
353
354    _custom_resize(wd, NULL, NULL, NULL);
355 }
356
357 /**
358  * Set the overlay object used for the background object.
359  *
360  * @param obj The bg object
361  * @return The content that is being used
362  *
363  * Return the content object which is set for this widget
364  *
365  * @ingroup Bg
366  */
367 EAPI Evas_Object *
368 elm_bg_overlay_get(const Evas_Object *obj)
369 {
370    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
371    Widget_Data *wd = elm_widget_data_get(obj);
372    if (!wd) return NULL;
373    return wd->overlay;
374 }
375
376 /**
377  * Get the overlay object used for the background object.
378  *
379  * @param obj The bg object
380  * @return The content that was being used
381  *
382  * Unparent and return the overlay object which was set for this widget
383  *
384  * @ingroup Bg
385  */
386 EAPI Evas_Object *
387 elm_bg_overlay_unset(Evas_Object *obj)
388 {
389    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
390    Widget_Data *wd = elm_widget_data_get(obj);
391    Evas_Object *overlay;
392    if (!wd) return NULL;
393    if (!wd->overlay) return NULL;
394    overlay = wd->overlay;
395    elm_widget_sub_object_del(obj, wd->overlay);
396    edje_object_part_unswallow(wd->base, wd->overlay);
397    wd->overlay = NULL;
398    _custom_resize(wd, NULL, NULL, NULL);
399    return overlay;
400 }
401
402 /**
403  * Set the size of a loaded image of the canvas of the bg.
404  *
405  * @param obj The bg object
406  * @param w The new width of the canvas image given.
407  * @param h The new height of the canvas image given.
408  *
409  * This function sets a new size for the canvas image of the given the bg.
410  *
411  */
412 EAPI void
413 elm_bg_load_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
414 {
415    ELM_CHECK_WIDTYPE(obj, widtype);
416    Widget_Data *wd = elm_widget_data_get(obj);
417    const char *p;
418    if (!wd) return;
419    wd->load_opts.w = w;
420    wd->load_opts.h = h;
421    if (!wd->img) return;
422    if (!(((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))))
423      evas_object_image_load_size_set(wd->img, w, h);
424 }
425