move elementary to trunk base. out of TMP/st.
[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  *
7  * The bg object is used for setting a solid background to a window or packing
8  * into any container object.
9  */
10
11 typedef struct _Widget_Data Widget_Data;
12
13 struct _Widget_Data
14 {
15    Evas_Object *base, *rect, *img, *overlay;
16    const char  *file, *group;
17    Elm_Bg_Option option;
18 };
19
20 static const char *widtype = NULL;
21
22 static void _del_hook(Evas_Object *obj);
23 static void _theme_hook(Evas_Object *obj);
24 static void _custom_resize(void *data, Evas *a, Evas_Object *obj, void *event_info);
25
26 static void
27 _del_hook(Evas_Object *obj)
28 {
29    Widget_Data *wd = elm_widget_data_get(obj);
30    free(wd);
31 }
32
33 static void
34 _theme_hook(Evas_Object *obj)
35 {
36    Widget_Data *wd = elm_widget_data_get(obj);
37    Evas_Coord w, h;
38
39    _elm_theme_object_set(obj, wd->base, "bg", "base", 
40                          elm_widget_style_get(obj));
41
42    if (wd->rect)
43      edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
44    if (wd->img)
45      edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
46    if (wd->overlay)
47      edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
48
49 // FIXME: if i don't do this, bg doesnt calc correctly. why?   
50    evas_object_geometry_get(wd->base, NULL, NULL, &w, &h);
51    evas_object_resize(wd->base, w, h);
52 }
53
54 static void
55 _custom_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
56 {
57    Widget_Data *wd = data;
58    Evas_Coord bx = 0, by = 0, bw = 0, bh = 0;
59    Evas_Coord iw = 0, ih = 0, mw = -1, mh = -1;
60    Evas_Coord fx = 0, fy = 0, fw = 0, fh = 0;
61    Evas_Coord nx = 0, ny = 0, nw = 0, nh = 0;
62    const char *p;
63
64    if ((!wd->img) || (!wd->file)) return;
65    if (((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))) return;
66
67    /* grab image size */
68    evas_object_image_size_get(wd->img, &iw, &ih);
69    if ((iw < 1) || (ih < 1)) return;
70
71    /* grab base object dimensions */
72    evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
73
74    /* set some defaults */
75    nx = bx;
76    ny = by;
77    nw = bw;
78    nh = bh;
79
80    switch (wd->option) 
81      {
82       case ELM_BG_OPTION_CENTER:
83         fw = nw = iw;
84         fh = nh = ih;
85         nx = ((bw - fw) / 2);
86         ny = ((bh - fh) / 2);
87         mw = iw;
88         mh = ih;
89         break;
90       case ELM_BG_OPTION_SCALE:
91         fw = bw;
92         fh = ((ih * fw) / iw);
93         if (fh < bh)
94           {
95              fh = bh;
96              fw = ((iw * fh) / ih);
97           }
98         fx = ((bw - fw) / 2);
99         fy = ((bh - fh) / 2);
100         break;
101       case ELM_BG_OPTION_TILE:
102         fw = iw;
103         fh = ih;
104         break;
105       case ELM_BG_OPTION_STRETCH:
106       default:
107         fw = bw;
108         fh = bh;
109         break;
110      }
111
112    evas_object_move(wd->img, nx, ny);
113    evas_object_resize(wd->img, nw, nh);
114    evas_object_image_fill_set(wd->img, fx, fy, fw, fh);
115
116    evas_object_size_hint_min_set(wd->img, mw, mh);
117    evas_object_size_hint_max_set(wd->img, mw, mh);
118 }
119
120 /**
121  * Add a new background to the parent
122  *
123  * @param parent The parent object
124  * @return The new object or NULL if it cannot be created
125  *
126  * @ingroup Bg
127  */
128 EAPI Evas_Object *
129 elm_bg_add(Evas_Object *parent)
130 {
131    Evas_Object *obj;
132    Evas *e;
133    Widget_Data *wd;
134
135    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
136
137    wd = ELM_NEW(Widget_Data);
138    e = evas_object_evas_get(parent);
139    if (!e) return NULL;
140    obj = elm_widget_add(e);
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         evas_object_image_file_set(wd->img, file, group);
207      }
208    evas_object_repeat_events_set(wd->img, EINA_TRUE);
209    edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
210    elm_widget_sub_object_add(obj, wd->img);
211    _custom_resize(wd, NULL, NULL, NULL);
212 }
213
214 /**
215  * Get the file (image or edje) used for the background
216  *
217  * @param obj The bg object
218  * @param file The file path
219  * @param group Optional key (group in Edje) within the file
220  *
221  * @ingroup Bg
222  */
223 EAPI void
224 elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group)
225 {
226    ELM_CHECK_WIDTYPE(obj, widtype);
227    Widget_Data *wd = elm_widget_data_get(obj);
228    if (file) *file = wd->file;
229    if (group) *group = wd->group;
230 }
231
232 /**
233  * Set the option used for the background image
234  *
235  * @param obj The bg object
236  * @param option The desired background option (TILE, SCALE)
237  *
238  * This sets the option used for manipulating the display of the background 
239  * image. The image can be tiled or scaled.
240  *
241  * @ingroup Bg
242  */
243 EAPI void 
244 elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option) 
245 {
246    ELM_CHECK_WIDTYPE(obj, widtype);
247    Widget_Data *wd;
248
249    wd = elm_widget_data_get(obj);
250    wd->option = option;
251    _custom_resize(wd, NULL, NULL, NULL);
252 }
253
254 /**
255  * Get the option used for the background image
256  *
257  * @param obj The bg object
258  * @return The desired background option (TILE, SCALE)
259  *
260  * @ingroup Bg
261  */
262 EAPI Elm_Bg_Option
263 elm_bg_option_get(const Evas_Object *obj)
264 {
265    ELM_CHECK_WIDTYPE(obj, widtype) 0;
266    Widget_Data *wd;
267
268    wd = elm_widget_data_get(obj);
269    return wd->option;
270 }
271
272 /**
273  * Set the option used for the background color
274  *
275  * @param obj The bg object
276  * @param r
277  * @param g
278  * @param b
279  *
280  * This sets the color used for the background rectangle.
281  *
282  * @ingroup Bg
283  */
284 EAPI void 
285 elm_bg_color_set(Evas_Object *obj, int r, int g, int b) 
286 {
287    ELM_CHECK_WIDTYPE(obj, widtype);
288    Widget_Data *wd;
289
290    wd = elm_widget_data_get(obj);
291    if (!wd->rect)
292      {
293         wd->rect = evas_object_rectangle_add(evas_object_evas_get(wd->base));
294         edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
295         elm_widget_sub_object_add(obj, wd->rect);
296         _custom_resize(wd, NULL, NULL, NULL);
297      }
298    evas_object_color_set(wd->rect, r, g, b, 255);
299 }
300
301 /**
302  * Get the option used for the background color
303  *
304  * @param obj The bg object
305  * @param r
306  * @param g
307  * @param b
308  *
309  * @ingroup Bg
310  */
311 EAPI void
312 elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b)
313 {
314    ELM_CHECK_WIDTYPE(obj, widtype);
315    Widget_Data *wd;
316
317    wd = elm_widget_data_get(obj);
318    evas_object_color_get(wd->rect, r, g, b, NULL);
319 }
320
321 /**
322  * Set the overlay object used for the background object.
323  *
324  * @param obj The bg object
325  * @param overlay The overlay object
326  *
327  * This provides a way for elm_bg to have an 'overlay' (such as animated fog)
328  * Once the over object is set, a previously set one will be deleted.
329  * If you want to keep that old content object, use the
330  * elm_bg_overlay_unset() function.
331  *
332  * @ingroup Bg
333  */
334 EAPI void
335 elm_bg_overlay_set(Evas_Object *obj, Evas_Object *overlay)
336 {
337    ELM_CHECK_WIDTYPE(obj, widtype);
338    Widget_Data *wd = elm_widget_data_get(obj);
339    if (!wd) return;
340    if (wd->overlay)
341      {
342         evas_object_del(wd->overlay);
343         wd->overlay = NULL;
344      }
345    if (overlay)
346      {
347         wd->overlay = overlay;
348         edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
349         elm_widget_sub_object_add(obj, wd->overlay);
350      }
351
352    _custom_resize(wd, NULL, NULL, NULL);
353 }
354
355 /**
356  * Set the overlay object used for the background object.
357  *
358  * @param obj The bg object
359  * @return The content that is being used
360  *
361  * Return the content object which is set for this widget
362  *
363  * @ingroup Bg
364  */
365 EAPI Evas_Object *
366 elm_bg_overlay_get(const Evas_Object *obj)
367 {
368    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
369    Widget_Data *wd = elm_widget_data_get(obj);
370    if (!wd) return NULL;
371    return wd->overlay;
372 }
373
374 /**
375  * Get the overlay object used for the background object.
376  *
377  * @param obj The bg object
378  * @return The content that was being used
379  *
380  * Unparent and return the overlay object which was set for this widget
381  *
382  * @ingroup Bg
383  */
384 EAPI Evas_Object *
385 elm_bg_overlay_unset(Evas_Object *obj)
386 {
387    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
388    Widget_Data *wd = elm_widget_data_get(obj);
389    Evas_Object *overlay;
390    if (!wd) return NULL;
391    if (!wd->overlay) return NULL;
392    overlay = wd->overlay;
393    elm_widget_sub_object_del(obj, wd->overlay);
394    edje_object_part_unswallow(wd->base, wd->overlay);
395    wd->overlay = NULL;
396    _custom_resize(wd, NULL, NULL, NULL);
397    return overlay;
398 }