[genlist] apply r71140 with local enhancement
[framework/uifw/elementary.git] / src / lib / elm_bg.c
index a08a0f4..df29d5b 100644 (file)
@@ -1,28 +1,27 @@
-#include <string.h>
-
 #include <Elementary.h>
 #include "elm_priv.h"
 
-/**
- * @defgroup Bg Bg
- * @ingroup Elementary
- *
- * The bg object is used for setting a solid background to a window or packing
- * into any container object.
- */
-
 typedef struct _Widget_Data Widget_Data;
 
 struct _Widget_Data
 {
-   Evas_Object *img, *custom_img;
+   Evas_Object *base, *rect, *img, *overlay;
    const char  *file, *group;
+   Elm_Bg_Option option;
+   struct
+     {
+        Evas_Coord w, h;
+     } load_opts;
 };
 
 static const char *widtype = NULL;
+
 static void _del_hook(Evas_Object *obj);
 static void _theme_hook(Evas_Object *obj);
 static void _custom_resize(void *data, Evas *a, Evas_Object *obj, void *event_info);
+static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
+static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
+static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
 
 static void
 _del_hook(Evas_Object *obj)
@@ -35,39 +34,139 @@ static void
 _theme_hook(Evas_Object *obj)
 {
    Widget_Data *wd = elm_widget_data_get(obj);
-   _elm_theme_object_set(obj, wd->img, "bg", "base", elm_widget_style_get(obj));
+   Evas_Coord w, h;
+
+   _elm_theme_object_set(obj, wd->base, "bg", "base",
+                         elm_widget_style_get(obj));
+
+   if (wd->rect)
+     edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
+   if (wd->img)
+     edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
+   if (wd->overlay)
+     edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
+
+   // FIXME: if i don't do this, bg doesnt calc correctly. why?
+   evas_object_geometry_get(wd->base, NULL, NULL, &w, &h);
+   evas_object_resize(wd->base, w, h);
 }
 
 static void
-_custom_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+_custom_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
 {
-   int iw = 0, ih = 0;
-   Evas_Coord x, y, w, h, ow = 0, oh = 0;
+   Widget_Data *wd = data;
+   Evas_Coord bx = 0, by = 0, bw = 0, bh = 0;
+   Evas_Coord iw = 0, ih = 0, mw = -1, mh = -1;
+   Evas_Coord fx = 0, fy = 0, fw = 0, fh = 0;
+   Evas_Coord nx = 0, ny = 0, nw = 0, nh = 0;
+   const char *p;
 
-   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
-   evas_object_image_size_get(obj, &iw, &ih);
+   if ((!wd->img) || (!wd->file)) return;
+   if (((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))) return;
 
+   /* grab image size */
+   evas_object_image_size_get(wd->img, &iw, &ih);
    if ((iw < 1) || (ih < 1)) return;
-   w = ow;
-   h = (ih * w) / iw;
-   if (h < oh)
+
+   /* grab base object dimensions */
+   evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
+
+   /* set some defaults */
+   nx = bx;
+   ny = by;
+   nw = bw;
+   nh = bh;
+
+   switch (wd->option)
+     {
+      case ELM_BG_OPTION_CENTER:
+         fw = nw = iw;
+         fh = nh = ih;
+         nx = ((bw - fw) / 2);
+         ny = ((bh - fh) / 2);
+         mw = iw;
+         mh = ih;
+         break;
+      case ELM_BG_OPTION_SCALE:
+         fw = bw;
+         fh = ((ih * fw) / iw);
+         if (fh < bh)
+           {
+              fh = bh;
+              fw = ((iw * fh) / ih);
+           }
+         fx = ((bw - fw) / 2);
+         fy = ((bh - fh) / 2);
+         break;
+      case ELM_BG_OPTION_TILE:
+         fw = iw;
+         fh = ih;
+         break;
+      case ELM_BG_OPTION_STRETCH:
+      default:
+         fw = bw;
+         fh = bh;
+         break;
+     }
+
+   evas_object_move(wd->img, nx, ny);
+   evas_object_resize(wd->img, nw, nh);
+   evas_object_image_fill_set(wd->img, fx, fy, fw, fh);
+
+   evas_object_size_hint_min_set(wd->img, mw, mh);
+   evas_object_size_hint_max_set(wd->img, mw, mh);
+}
+
+static void
+_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+   if (part && strcmp(part, "overlay")) return;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (content == wd->overlay) return;
+   if (wd->overlay) evas_object_del(wd->overlay);
+
+   wd->overlay = content;
+   if (content)
      {
-       h = oh;
-       w = (iw * h) / ih;
+        edje_object_part_swallow(wd->base, "elm.swallow.content", content);
+        elm_widget_sub_object_add(obj, content);
      }
-   x = (ow - w) / 2;
-   y = (oh - h) / 2;
-   evas_object_image_fill_set(obj, x, y, w, h);
+
+   _custom_resize(wd, NULL, NULL, NULL);
+}
+
+static Evas_Object *
+_content_get_hook(const Evas_Object *obj, const char *part)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd;
+   if (part && strcmp(part, "overlay")) return NULL;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return wd->overlay;
+}
+
+static Evas_Object *
+_content_unset_hook(Evas_Object *obj, const char *part)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd;
+   Evas_Object *overlay;
+   if (part && strcmp(part, "overlay")) return NULL;
+   wd = elm_widget_data_get(obj);
+   if (!wd || !wd->overlay) return NULL;
+   overlay = wd->overlay;
+   elm_widget_sub_object_del(obj, wd->overlay);
+   edje_object_part_unswallow(wd->base, wd->overlay);
+   wd->overlay = NULL;
+   _custom_resize(wd, NULL, NULL, NULL);
+   return overlay;
 }
 
-/**
- * Add a new background to the parent
- *
- * @param parent The parent object
- * @return The new object or NULL if it cannot be created
- *
- * @ingroup Bg
- */
 EAPI Evas_Object *
 elm_bg_add(Evas_Object *parent)
 {
@@ -75,65 +174,151 @@ elm_bg_add(Evas_Object *parent)
    Evas *e;
    Widget_Data *wd;
 
-   wd = ELM_NEW(Widget_Data);
-   e = evas_object_evas_get(parent);
-   obj = elm_widget_add(e);
+   ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
+
    ELM_SET_WIDTYPE(widtype, "bg");
    elm_widget_type_set(obj, "bg");
    elm_widget_sub_object_add(parent, obj);
    elm_widget_data_set(obj, wd);
    elm_widget_del_hook_set(obj, _del_hook);
    elm_widget_theme_hook_set(obj, _theme_hook);
-   elm_widget_can_focus_set(obj, 0);
+   elm_widget_content_set_hook_set(obj, _content_set_hook);
+   elm_widget_content_get_hook_set(obj, _content_get_hook);
+   elm_widget_content_unset_hook_set(obj, _content_unset_hook);
 
-   wd->img = edje_object_add(e);
-   _elm_theme_object_set(obj, wd->img, "bg", "base", "default");
-   elm_widget_resize_object_set(obj, wd->img);
+   elm_widget_can_focus_set(obj, EINA_FALSE);
+
+   wd->base = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->base, "bg", "base", "default");
+   elm_widget_resize_object_set(obj, wd->base);
+
+   evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE,
+                                  _custom_resize, wd);
+
+   wd->option = ELM_BG_OPTION_SCALE;
    return obj;
 }
 
-/**
- * Set the file (image or edje) used for the background
- *
- * @param obj The bg object
- * @param file The file path
- * @param group Optional key (group in Edje) within the file
- *
- * This sets the image file used in the background object. The image (or edje)
- * will be stretched (retaining aspect if its an image file) to completely fill
- * the bg object. This may mean some parts arte not visible.
- *
- * @ingroup Bg
- */
-EAPI void
+EAPI Eina_Bool
 elm_bg_file_set(Evas_Object *obj, const char *file, const char *group)
 {
-   ELM_CHECK_WIDTYPE(obj, widtype);
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
    Widget_Data *wd = elm_widget_data_get(obj);
    const char *p;
 
-   if (wd->custom_img)
+   if (wd->img)
      {
-       evas_object_del(wd->custom_img);
-       wd->custom_img = NULL;
+        evas_object_del(wd->img);
+        wd->img = NULL;
+     }
+   if (!file)
+     {
+        eina_stringshare_del(wd->file);
+        wd->file = NULL;
+        eina_stringshare_del(wd->group);
+        wd->group = NULL;
+        return EINA_TRUE;
      }
-   if (!file) return;
    eina_stringshare_replace(&wd->file, file);
    eina_stringshare_replace(&wd->group, group);
    if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
      {
-       wd->custom_img = edje_object_add(evas_object_evas_get(wd->img));
-       edje_object_file_set(wd->custom_img, file, group);
+        wd->img = edje_object_add(evas_object_evas_get(wd->base));
+        edje_object_file_set(wd->img, file, group);
      }
    else
      {
-       wd->custom_img = evas_object_image_add(evas_object_evas_get(wd->img));
-       evas_object_event_callback_add(wd->custom_img, EVAS_CALLBACK_RESIZE, 
-                                       _custom_resize, wd);
-       evas_object_image_file_set(wd->custom_img, file, group);
+        wd->img = evas_object_image_add(evas_object_evas_get(wd->base));
+        if ((wd->load_opts.w > 0) && (wd->load_opts.h > 0))
+          evas_object_image_load_size_set(wd->img, wd->load_opts.w, wd->load_opts.h);
+        evas_object_image_file_set(wd->img, file, group);
+     }
+   evas_object_repeat_events_set(wd->img, EINA_TRUE);
+   edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
+   elm_widget_sub_object_add(obj, wd->img);
+   _custom_resize(wd, NULL, NULL, NULL);
+
+   return EINA_TRUE;
+}
+
+EAPI void
+elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (file) *file = wd->file;
+   if (group) *group = wd->group;
+
+   return;
+}
+
+EAPI void
+elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   wd->option = option;
+   _custom_resize(wd, NULL, NULL, NULL);
+
+   return;
+}
+
+EAPI Elm_Bg_Option
+elm_bg_option_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) ELM_BG_OPTION_LAST;
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   return wd->option;
+}
+
+EAPI void
+elm_bg_color_set(Evas_Object *obj, int r, int g, int b)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd->rect)
+     {
+        wd->rect = evas_object_rectangle_add(evas_object_evas_get(wd->base));
+        edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
+        elm_widget_sub_object_add(obj, wd->rect);
+        _custom_resize(wd, NULL, NULL, NULL);
      }
-   elm_widget_sub_object_add(obj, wd->custom_img);
-   evas_object_repeat_events_set(wd->custom_img, 1);
-   edje_object_part_swallow(wd->img, "elm.swallow.background", wd->custom_img);
-   evas_object_show(wd->custom_img);
+   evas_object_color_set(wd->rect, r, g, b, 255);
+
+   return;
+}
+
+EAPI void
+elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd;
+
+   wd = elm_widget_data_get(obj);
+   evas_object_color_get(wd->rect, r, g, b, NULL);
+
+   return;
 }
+
+EAPI void
+elm_bg_load_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const char *p;
+   if (!wd) return;
+   wd->load_opts.w = w;
+   wd->load_opts.h = h;
+   if (!wd->img) return;
+   if (!(((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))))
+     evas_object_image_load_size_set(wd->img, w, h);
+
+   return;
+}
+