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