[revert] for deprecated winsets
authorWooHyun Jung <wh0705.jung@samsung.com>
Tue, 4 Jan 2011 01:11:45 +0000 (10:11 +0900)
committerWooHyun Jung <wh0705.jung@samsung.com>
Tue, 4 Jan 2011 01:11:45 +0000 (10:11 +0900)
22 files changed:
src/lib/Elementary.h.in
src/lib/Makefile.am
src/lib/elc_notepad.c [new file with mode: 0644]
src/lib/elm_actionsheet.c [new file with mode: 0644]
src/lib/elm_analogclock.c [new file with mode: 0644]
src/lib/elm_autocompleteview.c [new file with mode: 0644]
src/lib/elm_carousel.c [new file with mode: 0644]
src/lib/elm_datepicker.c [new file with mode: 0644]
src/lib/elm_gallery.c [new file with mode: 0644]
src/lib/elm_gridbox.c [new file with mode: 0644]
src/lib/elm_hor_scroller.c [new file with mode: 0644]
src/lib/elm_ratingbar.c [new file with mode: 0644]
src/lib/elm_scrolled_grid.c [new file with mode: 0644]
src/lib/elm_softkey.c [new file with mode: 0644]
src/lib/elm_tab.c [new file with mode: 0644]
src/lib/elm_tabbar.c [new file with mode: 0644]
src/lib/elm_timepicker.c [new file with mode: 0644]
src/lib/elm_titlebar.c [new file with mode: 0644]
src/lib/elm_wipercontrol.c [new file with mode: 0644]
src/lib/elm_zoomcontrols.c [new file with mode: 0644]
src/lib/els_hor_scroller.c [new file with mode: 0644]
src/lib/els_hor_scroller.h [new file with mode: 0644]

index ef2b3cf..0f27dff 100644 (file)
@@ -870,6 +870,22 @@ extern "C" {
     * "unfocused" - keyboard focus is gone
     */
 
+   /* composite widgets - these basically put together basic widgets above
+    * in convenient packages that do more than basic stuff */
+   typedef enum _Elm_Text_Format
+     {
+       ELM_TEXT_FORMAT_PLAIN_UTF8,
+       ELM_TEXT_FORMAT_MARKUP_UTF8
+     } Elm_Text_Format;
+   EINA_DEPRECATED EAPI Evas_Object *elm_notepad_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI void         elm_notepad_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format);
+   EINA_DEPRECATED EAPI void         elm_notepad_file_save(Evas_Object *obj, const char *file, Elm_Text_Format format);
+   EINA_DEPRECATED EAPI void         elm_notepad_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
+   EINA_DEPRECATED EAPI void         elm_notepad_autosave_set(Evas_Object *obj, Eina_Bool autosave);
+
+   /* smart callbacks called:
+    */
+
    typedef struct _Elm_Entry_Anchorview_Info Elm_Entry_Anchorview_Info;
    struct _Elm_Entry_Anchorview_Info
      {
@@ -1115,6 +1131,7 @@ extern "C" {
    EAPI void             elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
    EAPI void             elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
    EAPI void             elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
+
    /* smart callbacks called:
     * "clicked" - when the user double-clicked an item
     * "selected" - when the user selected an item
@@ -1122,6 +1139,16 @@ extern "C" {
     * "longpressed" - an item in the hoversel list is long-pressed
     */
 
+   // FIXME: incomplete - carousel. don't use this until this comment is removed
+   typedef struct _Elm_Carousel_Item Elm_Carousel_Item;
+   EAPI Evas_Object       *elm_carousel_add(Evas_Object *parent);
+   EAPI Elm_Carousel_Item *elm_carousel_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, Evas_Smart_Cb func, const void *data);
+   EAPI void               elm_carousel_item_del(Elm_Carousel_Item *item);
+   EAPI void               elm_carousel_item_select(Elm_Carousel_Item *item);
+   /* smart callbacks called:
+    * "clicked" - when the user clicks on a carousel item and becomes selected
+    */
+
    EAPI Evas_Object *elm_slider_add(Evas_Object *parent);
    EAPI void         elm_slider_label_set(Evas_Object *obj, const char *label);
    EAPI const char  *elm_slider_label_get(const Evas_Object *obj);
@@ -1880,6 +1907,37 @@ extern "C" {
     * "overflowed" - when discpicker item is changed to first item from last item
     * "underflowed" - when discpicker item is changed to last item from first item.
     */
+   /* available styles:
+    * default
+    */
+
+   EAPI Evas_Object *elm_timepicker_add(Evas_Object *parent);
+   EAPI void         elm_timepicker_time_set(Evas_Object *obj, int hrs, int min, int sec);
+   EAPI void         elm_timepicker_time_get(Evas_Object *obj, int *hrs, int *min, int *sec);
+   EAPI void         elm_timepicker_show_am_pm_set(Evas_Object *obj, Eina_Bool am_pm);
+   EAPI void         elm_timepicker_show_seconds_set(Evas_Object *obj, Eina_Bool seconds);
+   /* smart callback called:
+    * "changed" - when timepicker selected item is changed
+    */
+   /* available styles:
+    * default
+    */
+
+   EAPI Evas_Object *elm_datepicker_add(Evas_Object *parent);
+   EAPI void         elm_datepicker_date_set(Evas_Object *obj, int year, int month, int day);
+   EAPI void         elm_datepicker_date_get(const Evas_Object *obj, int *year, int *month, int *day);
+   EAPI void         elm_datepicker_date_min_set(Evas_Object *obj, int year, int month, int day);  // Not implemented
+   EAPI void         elm_datepicker_date_min_get(const Evas_Object *obj, int *year, int *month, int *day);
+   EAPI void         elm_datepicker_date_max_set(Evas_Object *obj, int year, int month, int day);  // Not implemented
+   EAPI void         elm_datepicker_date_max_get(const Evas_Object *obj, int *year, int *month, int *day);
+   EAPI void         elm_datepicker_date_format_set(Evas_Object *obj, const char *fmt);
+   EAPI const char  *elm_datepicker_date_format_get(const Evas_Object *obj);
+   /* smart callback called:
+    * "changed" - when datepicker selected item is changed
+    */
+   /* available styles:
+    * default
+    */
 
    /* datefield */
    typedef enum _Elm_Datefield_Layout
@@ -1908,6 +1966,15 @@ extern "C" {
    * "changed" - when datefield entry is changed, this signal is sent.
    */
    
+   /* titlebar */
+   EINA_DEPRECATED EAPI Evas_Object *elm_titlebar_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI void         elm_titlebar_label_set(Evas_Object *obj, const char *label);
+   EINA_DEPRECATED EAPI const char  *elm_titlebar_label_get(Evas_Object *obj);
+   EINA_DEPRECATED EAPI void         elm_titlebar_icon_set(Evas_Object *obj, Evas_Object *icon);
+   EINA_DEPRECATED EAPI Evas_Object *elm_titlebar_icon_get(Evas_Object *obj);
+   EINA_DEPRECATED EAPI void         elm_titlebar_end_set(Evas_Object *obj, Evas_Object *end);
+   EINA_DEPRECATED EAPI Evas_Object *elm_titlebar_end_get(Evas_Object *obj);
+
    /* popup */
    typedef enum _Elm_Popup_Response
      {
@@ -1992,6 +2059,45 @@ extern "C" {
    EAPI Eina_Bool    elm_ctxpopup_position_forced_get(Evas_Object *obj);
    EAPI void         elm_ctxpopup_area_set(Evas_Object *obj, Evas_Object *rect); 
    
+   /* Tab */
+   typedef enum _Elm_Tab_Move_Type
+     {
+        ELM_TAB_MOVE_LEFT = 0,
+        ELM_TAB_MOVE_RIGHT = 1
+     } Elm_Tab_Move_Type;
+
+   typedef enum _Elm_Tab_Mode_Type
+     {
+        ELM_TAB_PORTRAIT_2 = 2,
+        ELM_TAB_PORTRAIT_3 = 3,
+        ELM_TAB_PORTRAIT_4 = 4,
+        ELM_TAB_LANDSCAPE_2 = 12,
+        ELM_TAB_LANDSCAPE_3 = 13,
+        ELM_TAB_LANDSCAPE_4 = 14,
+        ELM_TAB_LANDSCAPE_5 = 15,
+     } Elm_Tab_Mode_Type;
+
+   typedef struct _Elm_Tab_Item Elm_Tab_Item;
+
+   EINA_DEPRECATED EAPI Evas_Object  *elm_tab_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI void          elm_tab_set(Evas_Object *obj, int mode);
+   EINA_DEPRECATED EAPI Elm_Tab_Item *elm_tab_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data);
+   EINA_DEPRECATED EAPI void          elm_tab_item_del(Elm_Tab_Item *item);
+   EINA_DEPRECATED EAPI void          elm_tab_item_select(Elm_Tab_Item *item);
+   EINA_DEPRECATED EAPI Evas_Object  *elm_tab_item_icon_get(Elm_Tab_Item *item);
+   EINA_DEPRECATED EAPI const char   *elm_tab_item_label_get(Elm_Tab_Item *item);
+   EINA_DEPRECATED EAPI void          elm_tab_item_label_set(Elm_Tab_Item *item, const char *label);
+   EINA_DEPRECATED EAPI void          elm_tab_item_badge_set(Elm_Tab_Item *item, const int badge);   
+   EINA_DEPRECATED EAPI Elm_Tab_Item *elm_tab_selected_item_get(Evas_Object *obj);   
+   EINA_DEPRECATED EAPI Elm_Tab_Item *elm_tab_first_item_get(Evas_Object *obj);   
+   EINA_DEPRECATED EAPI Elm_Tab_Item *elm_tab_last_item_get(Evas_Object *obj);   
+   EINA_DEPRECATED EAPI Eina_List    *elm_tab_items_get(Evas_Object *obj);   
+   EINA_DEPRECATED EAPI Elm_Tab_Item *elm_tab_item_prev(Elm_Tab_Item *item);   
+   EINA_DEPRECATED EAPI Elm_Tab_Item *elm_tab_item_next(Elm_Tab_Item *item);   
+   EINA_DEPRECATED EAPI void          elm_tab_move(Evas_Object *obj, int direction);
+   EINA_DEPRECATED EAPI void          elm_tab_edit_disable_set(Evas_Object *obj, Eina_Bool disable);
+   EINA_DEPRECATED EAPI Eina_Bool     elm_tab_edit_disable_get(Evas_Object *obj);
+
    /* tansit */
    typedef enum 
      {
@@ -2140,6 +2246,25 @@ extern "C" {
    EAPI Evas_Object *elm_navigationbar_ex_item_title_button_unset(Elm_Navigationbar_ex_Item* item, int button_type);
    EAPI void         elm_navigationbar_ex_animation_disable_set(Evas_Object *obj, Eina_Bool disable);
    
+   
+   /* Tab Bar */
+   #define TAB_BAR_SYSTEM_ICON_CONTACT "elm/icon/tabbar_contact/default" 
+   #define TAB_BAR_SYSTEM_ICON_GROUP "elm/icon/tabbar_group/default" 
+   #define TAB_BAR_SYSTEM_ICON_SONG "elm/icon/tabbar_song/default" 
+   #define TAB_BAR_SYSTEM_ICON_FAVORITES "elm/icon/tabbar_favorites/default" 
+   #define TAB_BAR_SYSTEM_ICON_SEARCH "elm/icon/tabbar_search/default" 
+   #define TAB_BAR_SYSTEM_ICON_MESSAGE "elm/icon/tabbar_message/default" 
+   #define TAB_BAR_SYSTEM_ICON_SETTING "elm/icon/tabbar_setting/default" 
+
+   EINA_DEPRECATED EAPI Evas_Object *elm_tabbar_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI Elm_Tab_Item *elm_tabbar_item_add(Evas_Object *obj, const char *icon_path, const char *label, Evas_Object *view);
+   EINA_DEPRECATED EAPI Evas_Object *elm_tabbar_item_icon_get(Elm_Tab_Item *it);
+   EINA_DEPRECATED EAPI const char  *elm_tabbar_item_label_get(Elm_Tab_Item *it);
+   EINA_DEPRECATED EAPI void         elm_tabbar_item_label_set(Elm_Tab_Item *it, const char *label);
+   EINA_DEPRECATED EAPI void         elm_tabbar_item_select(Elm_Tab_Item *it);
+   EINA_DEPRECATED EAPI void         elm_tabbar_edit_start(Evas_Object *obj);
+   EINA_DEPRECATED EAPI void         elm_tabbar_item_visible_set(Elm_Tab_Item *it, Eina_Bool bar);
+
    /* smart callbacks called:
     * "clicked" - when item clicked
     */
@@ -2236,6 +2361,19 @@ extern "C" {
    EAPI void         elm_searchbar_clear(Evas_Object *obj);
    EAPI void         elm_searchbar_boundary_rect_set(Evas_Object *obj, Eina_Bool boundary);
 
+   /* actionsheet */
+   typedef enum _Elm_Actionsheet_Button_Type 
+     {
+        ELM_ACTIONSHEET_BT_NORMAL = 0,
+        ELM_ACTIONSHEET_BT_CANCEL,
+        ELM_ACTIONSHEET_BT_DESTRUCTIVE
+     } Elm_Actionsheet_Button_Type;
+
+   EINA_DEPRECATED EAPI Evas_Object *elm_actionsheet_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI void         elm_actionsheet_title_set(Evas_Object *obj, const char *title);
+   EINA_DEPRECATED EAPI void         elm_actionsheet_button_add(Evas_Object *obj, const Elm_Actionsheet_Button_Type type, const char *title, void (*button_clicked_cb) (void *data, Evas_Object *obj, void *event_info), void *event_info);
+   EINA_DEPRECATED EAPI int          elm_actionsheet_button_title_get(Evas_Object *obj, const int index, char **title);
+
    /* colorpicker */
    EINA_DEPRECATED EAPI Evas_Object *elm_colorpicker_add(Evas_Object *parent);
    EINA_DEPRECATED EAPI void         elm_colorpicker_color_set(Evas_Object *obj, int r, int g , int b);
@@ -2288,6 +2426,51 @@ extern "C" {
     * "unfocused" - when an editfield is unfocused
     */
 
+
+
+   /* softkey */
+   typedef enum 
+     {
+        ELM_SK_LEFT_BTN,
+        ELM_SK_RIGHT_BTN,
+     } Elm_Softkey_Type;
+
+   /* softkey */
+   typedef struct _Elm_Softkey_Item Elm_Softkey_Item;
+   EINA_DEPRECATED EAPI Evas_Object *elm_softkey_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI Elm_Softkey_Item *elm_softkey_button_add(Evas_Object *obj, Elm_Softkey_Type type, Evas_Object *icon, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), const void *data);
+   EINA_DEPRECATED EAPI void         elm_softkey_button_del(Evas_Object *obj, Elm_Softkey_Type type);
+   EINA_DEPRECATED EAPI void         elm_softkey_button_show(Evas_Object *obj, Elm_Softkey_Type type);
+   EINA_DEPRECATED EAPI void         elm_softkey_button_hide(Evas_Object *obj, Elm_Softkey_Type type);
+
+   EINA_DEPRECATED EAPI Elm_Softkey_Item *elm_softkey_panel_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), const void *data);
+   EINA_DEPRECATED EAPI int          elm_softkey_panel_del(Evas_Object *obj);
+   EINA_DEPRECATED EAPI int          elm_softkey_panel_close(Evas_Object *obj);
+   EINA_DEPRECATED EAPI int          elm_softkey_panel_open(Evas_Object *obj);
+
+   EINA_DEPRECATED EAPI void         elm_softkey_item_icon_set(Elm_Softkey_Item *item, Evas_Object *icon);
+   EINA_DEPRECATED EAPI Evas_Object *elm_softkey_item_icon_get(Elm_Softkey_Item * item);
+   EINA_DEPRECATED EAPI void         elm_softkey_item_label_set(Elm_Softkey_Item *item, const char *label);
+   EINA_DEPRECATED EAPI const char  *elm_softkey_item_label_get(Elm_Softkey_Item * item);
+   EINA_DEPRECATED EAPI Eina_Bool    elm_softkey_item_disabled_get(Elm_Softkey_Item *item);
+   EINA_DEPRECATED EAPI void         elm_softkey_item_disabled_set(Elm_Softkey_Item *item, Eina_Bool disabled);
+   EINA_DEPRECATED EAPI void         elm_softkey_item_callback_set(Elm_Softkey_Item* item, void (*func)(void *data, Evas_Object *obj, void *event_info), const void *data );
+   /* smart callback called: 
+    * "clicked" - the user clicked the button, event_info: Softkey item
+    * "press"   - the user press the button, event_info: Softkey item
+    * "panel,show" - when the panel is shown
+    * "panel,hide" - when the panel is hidden
+    */
+       
+   /* gridbox */
+   EINA_DEPRECATED EAPI Evas_Object *elm_gridbox_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI void         elm_gridbox_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical);
+   EINA_DEPRECATED EAPI void         elm_gridbox_item_size_set(Evas_Object *obj, Evas_Coord h_itemsize, Evas_Coord v_itemsize);
+   EINA_DEPRECATED EAPI void         elm_gridbox_pack(Evas_Object *obj, Evas_Object *subobj);
+   EINA_DEPRECATED EAPI Eina_Bool    elm_gridbox_unpack(Evas_Object *obj, Evas_Object *subobj);
+   EINA_DEPRECATED EAPI Eina_List   *elm_gridbox_children_get(Evas_Object *obj);
+   EINA_DEPRECATED EAPI void         elm_gridbox_homogenous_padding_set(Evas_Object *obj, Eina_Bool homogenous);
+
    /* actionslider */                        
    typedef enum _Elm_Actionslider_Indicator_Pos  
      {                                         
@@ -2321,6 +2504,32 @@ extern "C" {
     * "indicator,position" - when a button reaches to the special position like "left", "right" and "center".
     */
    
+   /* gallery */
+   struct _Elm_Gallery_Item 
+     {
+        Evas_Object *parent;
+        Evas_Object *ly;
+        Evas_Object *obj;
+        const char *path;
+        int index;
+        Evas_Coord x, y, w, h;
+        Evas_Coord mw, mh;     
+        Eina_Bool on_hold : 1;
+        Eina_Bool on_show : 1;
+        Eina_Bool on_highquality : 1;          
+     };
+   typedef struct _Elm_Gallery_Item Elm_Gallery_Item;
+   EINA_DEPRECATED EAPI Evas_Object *elm_gallery_add(Evas_Object *parent);
+   EINA_DEPRECATED EAPI Eina_Bool    elm_gallery_data_set(Evas_Object *obj, Eina_List *list);
+   EINA_DEPRECATED EAPI Elm_Gallery_Item *elm_gallery_item_append(Evas_Object *obj, const char *photo_file);
+   EINA_DEPRECATED EAPI Elm_Gallery_Item *elm_gallery_item_prepend(Evas_Object *obj, const char *photo_file);
+   EINA_DEPRECATED EAPI void         elm_gallery_item_del(Elm_Gallery_Item *it);
+   EINA_DEPRECATED EAPI const char  *elm_gallery_item_file_get(Elm_Gallery_Item *it);
+   EINA_DEPRECATED EAPI void         elm_gallery_item_show(Elm_Gallery_Item *it);
+   EINA_DEPRECATED EAPI Eina_List   *elm_gallery_item_list_get(Evas_Object *obj);
+   EINA_DEPRECATED EAPI void         elm_gallery_set_type(Evas_Object *obj,int type);
+   EINA_DEPRECATED EAPI void         elm_gallery_set_max_count(Evas_Object *obj,int max_value);
+
    /* Sliding Drawer */
    typedef enum _Elm_SlidingDrawer_Pos 
      {
index cda6a16..bad3571 100644 (file)
@@ -58,6 +58,7 @@ elm_photo.c \
 elm_toolbar.c \
 elm_searchbar.c \
 elm_list.c \
+elm_carousel.c \
 elm_slider.c \
 elm_genlist.c \
 elm_check.c \
@@ -82,12 +83,17 @@ elm_conform.c \
 elm_mapbuf.c \
 elm_picker.c \
 elm_discpicker.c \
+elm_timepicker.c \
+elm_datepicker.c \
 elm_thumb.c \
 elm_config.c \
+elm_titlebar.c \
 elm_popup.c \
 elm_diskcontroller.c \
+elm_tab.c \
 elm_navigationbar.c \
 elm_navigationbar_ex.c\
+elm_tabbar.c \
 elm_transit.c \
 elm_animator.c \
 elm_editfield.c \
@@ -95,9 +101,16 @@ elm_colorpicker.c \
 elm_colorselector.c \
 elm_colorpalette.c \
 elm_ctxpopup.c \
+elm_actionsheet.c \
+elm_gridbox.c \
+elm_softkey.c \
 elm_actionslider.c \
+elm_hor_scroller.c \
+elm_autocompleteview.c \
 elm_controlbar.c \
+elm_gallery.c \
 elm_slidingdrawer.c \ 
+elm_wipercontrol.c \
 elm_dialoguegroup.c \
 elm_dayselector.c \
 elm_cnp_helper.c \
@@ -116,12 +129,15 @@ elc_anchorview.c \
 elc_fileselector.c \
 elc_fileselector_button.c \
 elc_hoversel.c \
+elc_notepad.c \
 elc_scrolled_entry.c \
 \
 els_pan.c \
 els_pan.h \
 els_scroller.c \
 els_scroller.h \
+els_hor_scroller.c \
+els_hor_scroller.h \
 els_box.c \
 els_box.h \
 els_icon.c \
diff --git a/src/lib/elc_notepad.c b/src/lib/elc_notepad.c
new file mode 100644 (file)
index 0000000..e81e339
--- /dev/null
@@ -0,0 +1,399 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+/**
+ * @defgroup Notepad Notepad
+ * @ingroup Elementary
+ *
+ * The notepad is an object for quickly loading a text file, displaying it,
+ * allowing editing of it and saving of changes back to the file loaded.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * NONE
+ *
+ * A notepad object contains a scroller and an entry. It is a convenience
+ * widget that loads a text file indicated, puts it in the scrollable entry
+ * and allows the user to edit it. Changes are written back to the original
+ * file after a short delay. The file to load and save to is specified by
+ * elm_notepad_file_set().
+ */
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *scr, *entry;
+   const char *file;
+   Elm_Text_Format format;
+   Ecore_Timer *delay_write;
+   Eina_Bool can_write : 1;
+   Eina_Bool autosave : 1;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _on_focus_hook(void *data, Evas_Object *obj);
+static void _load(Evas_Object *obj);
+static void _save(Evas_Object *obj);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->file) eina_stringshare_del(wd->file);
+   if (wd->delay_write)
+     {
+       ecore_timer_del(wd->delay_write);
+        if (wd->autosave) _save(obj);
+     }
+   free(wd);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_size_hint_min_set(obj, -1, -1);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static void
+_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (elm_widget_focus_get(obj)) elm_widget_focus_steal(wd->entry);
+}
+
+static char *
+_buf_append(char *buf, const char *str, int *len, int *alloc)
+{
+   int len2 = strlen(str);
+   if ((*len + len2) >= *alloc)
+     {
+       char *buf2 = realloc(buf, *alloc + len2 + 512);
+       if (!buf2) return NULL;
+       buf = buf2;
+       *alloc += (512 + len2);
+     }
+   strcpy(buf + *len, str);
+   *len += len2;
+   return buf;
+}
+
+static char *
+_load_file(const char *file)
+{
+   FILE *f;
+   size_t size;
+   int alloc = 0, len = 0;
+   char *text = NULL, buf[PATH_MAX];
+
+   f = fopen(file, "rb");
+   if (!f) return NULL;
+   while ((size = fread(buf, 1, sizeof(buf), f)))
+     {
+       buf[size] = 0;
+       text = _buf_append(text, buf, &len, &alloc);
+     }
+   fclose(f);
+   return text;
+}
+
+static char *
+_load_plain(const char *file)
+{
+   char *text;
+
+   text = _load_file(file);
+   if (text)
+     {
+        char *text2;
+
+       text2 = elm_entry_utf8_to_markup(text);
+       free(text);
+       return text2;
+     }
+   return NULL;
+}
+
+static void
+_load(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   char *text;
+   if (!wd) return;
+   if (!wd->file)
+     {
+       elm_entry_entry_set(wd->entry, "");
+       return;
+     }
+   switch (wd->format)
+     {
+     case ELM_TEXT_FORMAT_PLAIN_UTF8:
+       text = _load_plain(wd->file);
+       break;
+     case ELM_TEXT_FORMAT_MARKUP_UTF8:
+       text = _load_file(wd->file);
+       break;
+     default:
+       text = NULL;
+        break;
+     }
+   if (text)
+     {
+       elm_entry_entry_set(wd->entry, text);
+       free(text);
+     }
+   else
+     elm_entry_entry_set(wd->entry, "");
+}
+
+static void
+_save_markup_utf8(const char *file, const char *text)
+{
+   FILE *f;
+   
+   if ((!text) || (text[0] == 0))
+     {
+       ecore_file_unlink(file);
+       return;
+     }
+   f = fopen(file, "wb");
+   if (!f)
+     {
+       // FIXME: report a write error
+       return;
+     }
+   fputs(text, f); // FIXME: catch error
+   fclose(f);
+}
+
+static void
+_save_plain_utf8(const char *file, const char *text)
+{
+   char *text2;
+   
+   text2 = elm_entry_markup_to_utf8(text);
+   if (text2)
+     {
+       _save_markup_utf8(file, text2);
+       free(text2);
+     }
+}
+
+static void
+_save(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (!wd->file) return;
+   switch (wd->format)
+     {
+      case ELM_TEXT_FORMAT_PLAIN_UTF8:
+       _save_plain_utf8(wd->file, elm_entry_entry_get(wd->entry));
+       break;
+      case ELM_TEXT_FORMAT_MARKUP_UTF8:
+       _save_markup_utf8(wd->file, elm_entry_entry_get(wd->entry));
+       break;
+      default:
+       break;
+     }
+}
+
+static Eina_Bool
+_delay_write(void *data)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return ECORE_CALLBACK_CANCEL;
+   _save(data);
+   wd->delay_write = NULL;
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_entry_changed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   if (wd->delay_write)
+     {
+       ecore_timer_del(wd->delay_write);
+       wd->delay_write = NULL;
+     }
+   if (!wd->autosave) return;
+   wd->delay_write = ecore_timer_add(2.0, _delay_write, data);
+}
+
+static void
+_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_push(wd->scr);
+}
+
+static void
+_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_pop(wd->scr);
+}
+
+static void
+_freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_push(wd->scr);
+}
+
+static void
+_freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_widget_scroll_hold_pop(wd->scr);
+}
+
+/**
+ * Add a new notepad to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Notepad
+ */
+EAPI Evas_Object *
+elm_notepad_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "notepad");
+   elm_widget_type_set(obj, "notepad");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
+   elm_widget_data_set(obj, wd);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_can_focus_set(obj, 1);
+
+   wd->scr = elm_scroller_add(parent);
+   elm_widget_resize_object_set(obj, wd->scr);
+
+   wd->entry = elm_entry_add(parent);
+   evas_object_size_hint_weight_set(wd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(wd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_scroller_content_set(wd->scr, wd->entry);
+   evas_object_show(wd->entry);
+
+   elm_entry_entry_set(wd->entry, "");
+   evas_object_smart_callback_add(wd->entry, "changed", _entry_changed, obj);
+   
+   evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
+   
+   wd->autosave = EINA_TRUE;
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * This sets the file (and implicitly loads it) for the text to display and
+ * then edit. All changes are written back to the file after a short delay if
+ * the notepad object is set to autosave.
+ *
+ * @param obj The notepad object
+ * @param file The path to the file to load and save
+ * @param format The file format
+ *
+ * @ingroup Notepad
+ */
+EAPI void
+elm_notepad_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->delay_write)
+     {
+       ecore_timer_del(wd->delay_write);
+       wd->delay_write = NULL;
+     }
+   if (wd->autosave) _save(obj);
+   eina_stringshare_replace(&wd->file, file);
+   wd->format = format;
+   _load(obj);
+}
+
+/**
+ * This function writes any changes made to the file.
+ * All changes are written back to the file after a short delay.
+ *
+ * @param obj The notepad object
+ * @param file The path to the file to save
+ * @param format The file format
+ *
+ * @ingroup Notepad
+ */
+EAPI void 
+elm_notepad_file_save(Evas_Object *obj, const char *file, Elm_Text_Format format) 
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if ((!wd) || (!file)) return;
+   if (wd->delay_write)
+     {
+       ecore_timer_del(wd->delay_write);
+       wd->delay_write = NULL;
+     }
+   wd->format = format;
+   eina_stringshare_replace(&wd->file, file);
+   wd->delay_write = ecore_timer_add(2.0, _delay_write, obj);
+}
+
+/**
+ * This will enable or disable the scroller bounce mode for the notepad. See
+ * elm_scroller_bounce_set() for details
+ *
+ * @param obj The notepad object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Notepad
+ */
+EAPI void
+elm_notepad_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_scroller_bounce_set(wd->scr, h_bounce, v_bounce);
+}
+
+/**
+ * This sets the notepad object to 'autosave' the loaded text file or not.
+ *
+ * @param obj The notepad object
+ * @param autosave Autosave the loaded file or not
+ *
+ * @ingroup Notepad
+ */
+EAPI void 
+elm_notepad_autosave_set(Evas_Object *obj, Eina_Bool autosave) 
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->autosave = autosave;
+}
diff --git a/src/lib/elm_actionsheet.c b/src/lib/elm_actionsheet.c
new file mode 100644 (file)
index 0000000..6cc3333
--- /dev/null
@@ -0,0 +1,490 @@
+#include "Elementary.h"
+#include "elm_priv.h"
+
+#include <errno.h>
+
+/**
+ * @defgroup ActionSheet ActionSheet
+ * @ingroup Elementary
+ *
+ * Display an action sheet
+ *
+ */
+
+static const double ANIMATION_TIME = 0.4;
+
+/*
+ * object hierarchy
+ *
+ * actionsheet
+ *     bg
+ *     title
+ *     destructive_button
+ *     normal_buttons(rect)
+ *         normal_button1
+ *         normal_button2
+ *         ...
+ *     cancel_button
+ *
+ *
+ */
+
+typedef struct _Widget_Data
+{
+   Evas *e;
+   Evas_Object *parent, *win, *win_bg, *obj, *layout, *bt_box;
+
+   char *title;
+
+   /* last button delimeters: to use elm_box_pack_after() */
+   Evas_Object *bt_cancel, *bt_destructive, *bt_normal;
+   Evas_Object *bt_destructive_delim, *bt_normal_delim;
+
+   Eina_List *cb_data_list;
+
+   Evas_Coord show_x, show_y, hide_x, hide_y;
+   Evas_Coord curr_x, curr_y;
+   Ecore_Timer *layout_timer;
+
+} Widget_Data;
+
+typedef struct _Button_Cb_Data_Wrapper
+{
+   Evas_Object *obj;   // elm_widget
+   void (*cb_func) (void *, Evas_Object *, void *);
+   void * cb_data;
+   char * button_title;
+} Button_Cb_Data_Wrapper;
+
+/*
+ * Internal functions
+ */
+
+/*
+ * hooks
+ */
+static void
+_button_cb_data_wrapper_free(Button_Cb_Data_Wrapper *dw)
+{
+   if (dw->button_title) free(dw->button_title);
+   free(dw);
+}
+
+static void
+_really_del(void *data, Elm_Transit* transit)
+{
+   Widget_Data *wd = (Widget_Data *) data;
+
+   evas_object_del(wd->layout);
+   evas_object_del(wd->win_bg);
+
+   /* free widget data */
+   if(wd->title) free(wd->title);
+
+   // free eina_list
+   Eina_List *l;
+   Button_Cb_Data_Wrapper *dw;
+   EINA_LIST_FOREACH(wd->cb_data_list, l, dw)
+      _button_cb_data_wrapper_free(dw);
+   eina_list_free(wd->cb_data_list);
+
+   free(wd);
+}
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   // cut sub objects
+   elm_widget_sub_object_del(obj, wd->layout);
+   elm_widget_sub_object_del(obj, wd->win_bg);
+   elm_widget_resize_object_set(obj, NULL);
+   elm_widget_hover_object_set(obj, NULL);
+   // cut from parent
+   elm_widget_sub_object_del(wd->parent, obj);
+
+   edje_object_signal_emit(elm_layout_edje_get(wd->win_bg), "hide", "actionsheet");
+}
+
+Button_Cb_Data_Wrapper *
+_button_cb_data_wrapper_add(
+               Evas_Object *obj, 
+               void (*cb_func) (void *, Evas_Object *, void *), 
+               void *cb_data, 
+               const char* button_title)
+{
+   Button_Cb_Data_Wrapper *dw;
+
+   dw = (Button_Cb_Data_Wrapper *)calloc(1, sizeof(Button_Cb_Data_Wrapper));
+   dw->obj = obj;
+   dw->cb_func = cb_func;
+   dw->cb_data = cb_data;
+   dw->button_title = strdup(button_title);
+
+   return dw;
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   // do animation     
+   Elm_Transit * transit = elm_transit_add(wd->layout);
+   elm_transit_fx_insert(transit, elm_fx_translation_add(wd->layout, wd->show_x, wd->show_y, wd->hide_x, wd->hide_y));
+   elm_transit_completion_callback_set(transit, _really_del, wd);
+   elm_transit_curve_style_set(transit, ELM_ANIMATOR_CURVE_IN);
+   elm_transit_run(transit, ANIMATION_TIME-0.1);
+   elm_transit_del(transit);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+
+}
+
+/*
+ * callbacks
+ */
+static void
+_sub_del(void *data, Evas_Object *obj, void *event_info)
+{
+
+}
+
+static void
+_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   int x, y, w, h;
+   int minw, minh;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   // win_bg
+   evas_object_geometry_get(wd->parent,  &x, &y, &w, &h);      // assume parent object is a window
+   //fprintf(stderr, ">>> parent: %d %d %d %d\n", x, y, w, h);
+   evas_object_resize(wd->win_bg, w, h);
+   evas_object_move(wd->win_bg, x, y);
+
+   // layout
+   evas_object_size_hint_weight_set(wd->layout, EVAS_HINT_EXPAND, 0); 
+   evas_object_size_hint_align_set(wd->layout, 0.5, 1);
+
+   edje_object_size_min_calc(elm_layout_edje_get(wd->layout), &minw, &minh);
+   fprintf(stderr, ">>> layout's min size(by calc): %d %d %d\n", minw, minh, w);
+
+   evas_object_resize(wd->layout, w, minh);
+
+   // Store show/hide location into wd
+   //evas_object_move(wd->layout, 0, h - minh);
+   wd->show_x = 0;
+   wd->show_y = h - minh;
+   wd->hide_x = 0;
+   wd->hide_y = h;
+
+   evas_object_geometry_get(wd->bt_box, &x, &y, &w, &h);
+   fprintf(stderr, ">>> bt_box: %d %d %d %d\n", x, y, w, h);
+   evas_object_size_hint_min_get(wd->bt_box, &w, &h);
+   fprintf(stderr, ">>> bt_box(size_hint_min): %d %d \n", w, h);
+
+}
+
+static inline int
+_move_layout(Widget_Data *wd, const int until, const int offset)
+{
+    wd->curr_y += offset;
+    if(offset < 0) 
+      {
+         if(wd->curr_y < until) wd->curr_y = until;
+      } 
+    else 
+      {
+         if(wd->curr_y > until) wd->curr_y = until;
+      }
+
+    evas_object_move(wd->layout, wd->curr_x, wd->curr_y);
+
+    if(wd->curr_y == until) 
+      {
+         edje_object_signal_emit(elm_layout_edje_get(wd->layout), "elm,actionsheet,event_block_off", "elm");
+         return 0;
+      }
+    else 
+        return 1;
+}
+
+static void
+_show_animation_end_cb(void *data, Elm_Transit* transit)
+{
+   Widget_Data *wd = (Widget_Data *)data;
+   // unblock event 
+   edje_object_signal_emit(elm_layout_edje_get(wd->layout), "elm,actionsheet,event_block_off", "elm");
+}
+
+static int
+_show_layout(void *data)
+{
+   Widget_Data *wd = (Widget_Data *)data;
+   return _move_layout(wd, wd->show_y, -90);
+}
+
+static void
+_show(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   //int x, y, w, h;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   _resize(wd, wd->e, obj, obj);
+
+   evas_object_show(wd->win_bg);
+   evas_object_show(wd->layout);
+
+   // move to hide position
+   evas_object_move(wd->layout, wd->hide_x, wd->hide_y);
+   // block events
+   edje_object_signal_emit(elm_layout_edje_get(wd->layout), "elm,actionsheet,event_block_on", "elm");
+
+   // animate to show position
+   wd->curr_x = wd->hide_x;
+   wd->curr_y = wd->hide_y;
+
+
+   //ecore_timer_add(0.033, _show_layout, wd);
+
+   Elm_Transit * transit = elm_transit_add(wd->layout);
+   elm_transit_fx_insert(transit, elm_fx_translation_add(wd->layout, wd->hide_x, wd->hide_y, wd->show_x, wd->show_y));
+   elm_transit_completion_callback_set(transit, _show_animation_end_cb, wd);
+   elm_transit_curve_style_set(transit, ELM_ANIMATOR_CURVE_OUT);
+   elm_transit_run(transit, ANIMATION_TIME);
+   elm_transit_del(transit);
+
+   edje_object_signal_emit(elm_layout_edje_get(wd->layout), "show", "actionsheet");
+   edje_object_signal_emit(elm_layout_edje_get(wd->win_bg), "show", "actionsheet");
+}
+
+static void
+_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   evas_object_hide(wd->layout);
+}
+
+static void
+_button_cb_wrapper(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Button_Cb_Data_Wrapper *dw = (Button_Cb_Data_Wrapper *)data;
+   dw->cb_func(dw->cb_data, dw->obj, dw->button_title);
+}
+
+/**
+ * Add a new actionsheet to the parent
+ * Object constructor
+ *
+ * @param      parent  The parent object
+ * @return     The new actionsheet object, or null if it can't be created.
+ *
+ * @ingroup    ActionSheet
+ */
+EAPI Evas_Object *
+elm_actionsheet_add (Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Widget_Data *wd;
+
+   /* widget data */
+   wd = ELM_NEW(Widget_Data);  // allocate memory
+
+   /* widget object */
+   wd->e = evas_object_evas_get(parent);
+   obj = elm_widget_add(wd->e);        // get a new smart object(=widget)
+   elm_widget_type_set(obj, "actionsheet");    // set a smart object's type name
+
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);       // store wd pointer to smart_data->data 
+
+   elm_widget_del_pre_hook_set(obj, _del_pre_hook);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_theme_hook_set(obj, _theme_hook);        
+
+   /* actionsheet layout */
+   wd->layout = elm_layout_add(parent);
+   elm_layout_theme_set(wd->layout, "actionsheet", "base", "default");
+   evas_object_size_hint_weight_set(wd->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(wd->layout, 0.5, 1);
+   elm_widget_sub_object_add(obj, wd->layout);
+   elm_widget_hover_object_set(obj, wd->layout);
+
+   /* win_bg */
+   wd->win_bg = elm_layout_add(parent);
+   elm_layout_theme_set(wd->win_bg, "actionsheet", "bg", "default");
+   elm_widget_sub_object_add(obj, wd->win_bg);
+   elm_widget_resize_object_set(obj, wd->win_bg);
+
+   /* bt_box */
+   wd->bt_box = elm_box_add(wd->layout);
+   evas_object_size_hint_weight_set(wd->bt_box, 0, EVAS_HINT_EXPAND);
+   elm_layout_content_set(wd->layout, "v_sw", wd->bt_box);
+   evas_object_show(wd->bt_box);
+
+   /* set Widget_Data */
+   wd->parent = parent;
+   wd->obj = obj;
+
+#ifdef SKIP
+#endif
+
+   /* set callbacks */
+   /* win cb */
+
+   /* obj cb */
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
+
+   _resize(wd, wd->e, obj, obj);
+
+
+   fprintf(stderr, ">>>>> after:adding layout\n");
+   return obj;
+}
+
+/**
+ * @brief                      Get title of button with given index
+ * @param[in]          obj     is an actionsheet object.
+ * @param[in]          index   is the index of button
+ * @param[out]         title   is button's title
+ * @return                     length of the string
+ * @retval                     -EINVAL         Invalid index
+ */
+EAPI int
+elm_actionsheet_button_title_get (
+               Evas_Object *obj,
+               const int index,
+               char **title )
+{
+//   Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj);
+
+   return 0;
+}
+
+/**
+ * @brief              Add a button with given title.
+ *                             Can add normal button only.
+ * @param[in]  obj             An actionsheet.
+ * @param[in]  type    The type of the button to be added.
+ * @param[in]  title   Title string.
+ * @return             void
+ */
+EAPI void 
+elm_actionsheet_button_add (
+               Evas_Object *obj, 
+               const Elm_Actionsheet_Button_Type type, 
+               const char *title,
+               void (*cb_func) (void *data, Evas_Object *obj, void *event_info),
+               void *cb_data)
+{
+   Evas_Object **target = NULL;
+   char *button_style;
+   Widget_Data *wd;
+   int w, h;   
+   int box_w, box_h;
+
+   wd = (Widget_Data *) elm_widget_data_get(obj);
+
+   switch(type) 
+     {
+      case ELM_ACTIONSHEET_BT_CANCEL:
+         target = &(wd->bt_cancel);    
+         button_style = "cancel";
+         break;
+      case ELM_ACTIONSHEET_BT_DESTRUCTIVE:
+         target = &(wd->bt_destructive);
+         button_style = "destructive";
+         break;
+      case ELM_ACTIONSHEET_BT_NORMAL:
+         target = &(wd->bt_normal);
+         button_style = "normal";
+         break;
+      default:
+         return;
+     }
+   // case: cancel, destructive
+   // if button object is already exist, just change title
+   if ( type != ELM_ACTIONSHEET_BT_NORMAL && *target != NULL ) 
+     {
+        elm_button_label_set(*target, title);
+     }
+   else 
+     {
+        *target = elm_layout_add(obj);
+        elm_layout_theme_set(*target, "actionsheet", "button", button_style);
+        edje_object_part_text_set(elm_layout_edje_get(*target), "text", title);
+        evas_object_size_hint_weight_set(*target, 0, EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(*target, EVAS_HINT_FILL, 0);
+        evas_object_show(*target);
+
+        // set callback wrapper
+        Button_Cb_Data_Wrapper *dw = _button_cb_data_wrapper_add(obj, cb_func, cb_data, title);
+        edje_object_signal_callback_add(elm_layout_edje_get(*target), "elm,action,press", "", _button_cb_wrapper, dw);
+        // store data wrapper into eina list (to free all)
+        wd->cb_data_list = eina_list_append(wd->cb_data_list, dw);
+
+        switch (type) {
+           case ELM_ACTIONSHEET_BT_DESTRUCTIVE:
+              elm_box_pack_start(wd->bt_box, *target);
+              if(NULL == wd->bt_normal_delim) {
+                   wd->bt_normal_delim = *target;
+              }
+              break;
+
+           case ELM_ACTIONSHEET_BT_NORMAL:
+              if(NULL == wd->bt_normal_delim) {
+                   elm_box_pack_start(wd->bt_box, *target);
+              }
+              else {
+                   elm_box_pack_after(wd->bt_box, *target, wd->bt_normal_delim);
+              }
+              wd->bt_normal_delim = *target;
+              break;
+
+           case ELM_ACTIONSHEET_BT_CANCEL:
+              elm_box_pack_end(wd->bt_box, *target);
+              break;
+
+           default:
+              fprintf(stderr, ">>> wrong button type\n");
+              evas_object_del(*target);
+              return;
+        }
+
+        evas_object_size_hint_min_get(wd->bt_box, &box_w, &box_h);
+        edje_object_size_min_calc(elm_layout_edje_get(*target), &w, &h);
+        //evas_object_size_hint_min_get(*target, &w, &h);
+        fprintf(stderr, ">>> calc. box's h: %d + %d\n", box_h, h);
+        evas_object_size_hint_min_set(wd->bt_box, box_w>w?box_w:w, box_h+h);
+
+   }
+
+   _resize(wd, wd->e, obj, obj);
+}
+
+
+/**
+ * @brief              Set actionsheet title
+ *                             Can add normal button only.
+ * @param[in]  obj     is an actionsheet.
+ * @param[in]  title   title string. If NULL, unset existing title.
+ * @return             void
+ */
+EAPI void 
+elm_actionsheet_title_set (
+               Evas_Object *obj, 
+               const char *title)
+{
+//   Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj);
+}
+
+/* end of file */
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/src/lib/elm_analogclock.c b/src/lib/elm_analogclock.c
new file mode 100644 (file)
index 0000000..c5b6b04
--- /dev/null
@@ -0,0 +1,216 @@
+
+
+/**
+ *
+ * @defgroup Analogclock Analogclock
+ * @ingroup Elementary
+ *
+ * This is an analogclock.
+ */
+
+
+/*
+ *
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define dbg(fmt,args...) printf("[%s:%d] "fmt"\n", __FILE__, __LINE__, ##args); 
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+       Evas_Object *dial,
+                               *hand_hour,
+                               *hand_min;
+
+       Ecore_Timer *ticker;
+
+       int hour,
+               min;
+};
+
+
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _disable_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static Eina_Bool _ticker(void *data);
+static void _time_update(Evas_Object *obj);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       if (wd->ticker) ecore_timer_del(wd->ticker);
+       free(wd);
+}
+
+static Eina_Bool
+_ticker(void *data)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+       double t;
+       struct timeval timev;
+
+       gettimeofday(&timev, NULL);
+       t = ((double)(1000000 - timev.tv_usec)) / 1000000.0;
+       wd->ticker = ecore_timer_add(t, _ticker, data);
+       _time_update(data);
+       return 0;
+}
+
+static Eina_Bool
+_idle_draw (void *data)
+{
+       _ticker(data);
+       return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _time_update(data);
+}
+
+static void
+_object_rotate(Evas_Object *obj, double degree)
+{
+       const Evas_Map *m;
+       Evas_Map *m2;
+       Evas_Coord x, y, w, h;
+
+       evas_object_geometry_get (obj, &x, &y, &w, &h);
+       evas_object_hide (obj);
+
+       m = evas_object_map_get (obj);
+       if (m != NULL)
+               m2 = evas_map_dup(m);
+       else {
+               m2 = evas_map_new(4);
+       }
+
+       evas_map_util_points_populate_from_object (m2, obj);
+       evas_map_util_rotate (m2, degree, x+w/2, y+h/2);
+       evas_object_map_set (obj, m2);
+       evas_object_map_enable_set(obj, 1);
+       evas_map_free (m2);
+       evas_object_show (obj);
+}
+
+static void
+_time_update(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       double degree;
+       Evas_Coord x, y, w, h;
+       struct timeval timev;
+       struct tm *tm;
+       time_t tt;
+
+       evas_object_geometry_get (wd->dial, &x, &y, &w, &h);
+       if (w <= 0 || h <= 0) {
+               return;
+       }
+
+       gettimeofday(&timev, NULL);
+       tt = (time_t)(timev.tv_sec);
+       tzset();
+       tm = localtime(&tt);
+       if (tm)
+       {
+               wd->hour = tm->tm_hour;
+               wd->min = tm->tm_min;
+               if (wd->hour > 12) wd->hour -= 12;
+       }
+
+       degree = 6 * wd->min;
+       _object_rotate (wd->hand_min, degree);
+
+       degree = 30 * wd->hour + (wd->min / 2);
+       _object_rotate (wd->hand_hour, degree);
+}
+
+/*
+ * FIXME:
+ */
+static void
+_theme_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       _elm_theme_object_set(obj,wd->dial, "analogclock", "base", elm_widget_style_get(obj));
+
+       _sizing_eval(obj);
+
+       evas_object_show (wd->dial);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+       Evas_Coord w, h;
+
+       if (!wd) return;
+
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       edje_object_size_min_restricted_calc(wd->dial, &minw, &minh, minw, minh);   
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+
+       evas_object_size_hint_min_get(obj, &w, &h);
+       if (w > minw) minw = w;
+       if (h > minw) minh = h;
+
+       evas_object_size_hint_min_set(obj, minw, minh);
+       evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+/**
+ * Add a new analog clock to the parent
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ */
+EAPI Evas_Object *
+elm_analogclock_add(Evas_Object *parent)
+{
+       Evas_Object *obj;
+       Evas *e;
+       Widget_Data *wd;
+
+       wd = ELM_NEW(Widget_Data);
+       e = evas_object_evas_get(parent);
+       obj = elm_widget_add(e);
+       elm_widget_type_set(obj, "analogclock");
+       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);
+
+       wd->dial = edje_object_add(e);
+
+       _elm_theme_object_set(obj,wd->dial, "analogclock", "base", "default");
+
+       wd->hand_hour = edje_object_part_object_get (wd->dial, "hour");
+       wd->hand_min = edje_object_part_object_get (wd->dial, "minute");
+
+       evas_object_event_callback_add(wd->dial, EVAS_CALLBACK_MOVE, _move, obj);
+
+       elm_widget_resize_object_set(obj, wd->dial);
+       wd->hour = 0;
+       wd->min = 0;
+
+       _sizing_eval(obj);
+
+       ecore_idler_add (_idle_draw, obj);
+
+       return obj;
+}
+
diff --git a/src/lib/elm_autocompleteview.c b/src/lib/elm_autocompleteview.c
new file mode 100644 (file)
index 0000000..01c3ccb
--- /dev/null
@@ -0,0 +1,354 @@
+#include <Elementary.h>\r
+#include "elm_priv.h"\r
+#include <string.h>\r
+\r
+/**\r
+ * @defgroup Autocompleteview Autocompleteview\r
+ * @ingroup Elementary\r
+ *\r
+ * This widget show's the completed strings in a dropdown list \r
+ * based on the initial few characters entered by the user.\r
+ *\r
+ */\r
+\r
+typedef struct _Widget_Data Widget_Data;\r
+\r
+struct _Widget_Data\r
+{\r
+   Evas_Object *editfield;\r
+   Evas_Object *hover;\r
+   Evas_Object *layout;\r
+   Evas_Object *list;\r
+   Evas_Object *entry;\r
+   Eina_List *data_list;\r
+   Eina_Bool text_set : 1;\r
+   elmautocompleteview_matchfunction func;\r
+   void *data;\r
+   int threshold;\r
+};\r
+\r
+static void _editfield_clicked_cb(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+   evas_object_smart_callback_call(data, "clicked", NULL);\r
+}\r
+\r
+static void _entry_changed_cb(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(data);\r
+   const char *text = NULL;\r
+   int textlen = 0;\r
+   char *real = NULL,*res = NULL;\r
+   Eina_List *l;\r
+   Eina_Bool textfound = EINA_FALSE;\r
+   if(!wd) return;\r
+   if (elm_widget_disabled_get(data)) return;\r
+   if(wd->text_set)\r
+     {\r
+        evas_object_hide(wd->hover);\r
+        wd->text_set = EINA_FALSE;\r
+        return;\r
+     }\r
+   text = elm_entry_entry_get(obj);\r
+   if(text == NULL)\r
+      return;  \r
+   textlen  = strlen(text);\r
+   if(textlen <wd->threshold)\r
+     {\r
+        evas_object_hide(wd->hover);\r
+        return;\r
+     }         \r
+   evas_object_hide(wd->hover);\r
+   if(wd->func)\r
+     {\r
+        textfound = wd->func(data,text,wd->list,wd->data);\r
+     }\r
+   else if(wd->data_list) \r
+     {\r
+        elm_list_clear(wd->list);\r
+        EINA_LIST_FOREACH(wd->data_list, l, real) \r
+          {\r
+             res  = strcasestr(real,text);\r
+             if(res)\r
+               {\r
+                  elm_list_item_append(wd->list, real, NULL, NULL, \r
+                                       NULL, NULL);\r
+                  textfound=EINA_TRUE;\r
+               }\r
+          }\r
+     }\r
+   else\r
+      return;\r
+   if(textfound)\r
+     {\r
+        elm_list_go(wd->list);         \r
+        evas_object_show(wd->hover);\r
+     }\r
+\r
+}\r
+\r
+static void\r
+_del_pre_hook(Evas_Object *obj)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(wd->hover)\r
+      evas_object_del(wd->hover);\r
+}\r
+\r
+\r
+static void\r
+_del_hook(Evas_Object *obj)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   free(wd);\r
+}\r
+\r
+static void\r
+_sizing_eval(Evas_Object *obj)\r
+{\r
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;\r
+\r
+   evas_object_size_hint_min_set(obj, minw, minh);\r
+   evas_object_size_hint_max_set(obj, maxw, maxh);\r
+}\r
+\r
+static void\r
+_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+   _sizing_eval(data);\r
+}\r
+\r
+static void\r
+_hover_clicked(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+   printf("\n\ncurrently nothin to be done\n");\r
+}\r
+\r
+static void _list_click( void *data, Evas_Object *obj, void *event_info )\r
+{\r
+   Elm_List_Item *it = (Elm_List_Item *) elm_list_selected_item_get(obj);\r
+   Widget_Data *wd = elm_widget_data_get(data);\r
+   if((it==NULL)||(wd==NULL))\r
+      return;\r
+   const char *text = elm_list_item_label_get(it);\r
+   evas_object_smart_callback_call((Evas_Object *)data, "selected", (void *)text);\r
+   if(wd->data_list)\r
+     {\r
+        if(text!=NULL)\r
+          {\r
+             elm_entry_entry_set(wd->entry, text);\r
+             elm_entry_cursor_end_set(wd->entry);\r
+             wd->text_set =  EINA_TRUE;\r
+          }\r
+     }\r
+}\r
+\r
+static int\r
+_eina_cmp_str(const char *a, const char *b)\r
+{\r
+   return strcasecmp(a,b);\r
+}\r
+\r
+\r
+/**\r
+ * Add a new Autocompleteview object\r
+ *\r
+ * @param parent The parent object\r
+ * @return The new object or NULL if it cannot be created\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI Evas_Object *\r
+elm_autocompleteview_add(Evas_Object *parent)\r
+{\r
+   Evas_Object *obj;\r
+   Evas *e;\r
+   Widget_Data *wd;\r
+\r
+   wd = ELM_NEW(Widget_Data);\r
+   e = evas_object_evas_get(parent);\r
+   obj = elm_widget_add(e);\r
+   elm_widget_type_set(obj, "autocompleteview");\r
+   elm_widget_sub_object_add(parent, obj);\r
+   elm_widget_data_set(obj, wd);\r
+   elm_widget_del_pre_hook_set(obj, _del_pre_hook);\r
+   elm_widget_del_hook_set(obj, _del_hook);\r
+\r
+   wd->editfield = elm_editfield_add(parent);\r
+   elm_widget_resize_object_set(obj, wd->editfield);\r
+   elm_editfield_entry_single_line_set(wd->editfield, EINA_TRUE);\r
+   evas_object_size_hint_weight_set(wd->editfield, 0, EVAS_HINT_EXPAND);\r
+   evas_object_size_hint_align_set(wd->editfield, 0, EVAS_HINT_FILL);\r
+   evas_object_event_callback_add(wd->editfield,\r
+                                  EVAS_CALLBACK_CHANGED_SIZE_HINTS,\r
+                                  _changed_size_hints, obj);\r
+   wd->threshold = 1;\r
+   wd->entry = elm_editfield_entry_get(wd->editfield);\r
+\r
+   evas_object_smart_callback_add(wd->editfield, "clicked", _editfield_clicked_cb, obj);\r
+   evas_object_smart_callback_add(wd->entry, "changed", _entry_changed_cb, obj);\r
+\r
+   wd->hover = elm_hover_add(obj);\r
+   elm_hover_parent_set(wd->hover, parent);\r
+   elm_hover_target_set(wd->hover, wd->editfield);\r
+\r
+   wd->layout = elm_layout_add(wd->hover);\r
+   elm_layout_theme_set(wd->layout,"autocompleteview","base","default");\r
+   wd->list = elm_list_add(wd->layout);\r
+   evas_object_size_hint_weight_set(wd->list, EVAS_HINT_EXPAND, 0.0);\r
+   evas_object_size_hint_align_set(wd->list, EVAS_HINT_FILL, EVAS_HINT_FILL);\r
+   elm_list_horizontal_mode_set(wd->list, ELM_LIST_COMPRESS);\r
+   elm_object_style_set(wd->list,"autocompleteview");\r
+   elm_list_go(wd->list);\r
+   evas_object_smart_callback_add(wd->list, "selected", _list_click, obj);\r
+   elm_layout_content_set( wd->layout, "elm.swallow.content", wd->list );\r
+   elm_hover_content_set(wd->hover,\r
+                         elm_hover_best_content_location_get(wd->hover,\r
+                                                             ELM_HOVER_AXIS_VERTICAL),\r
+                         wd->layout);\r
+   evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked, obj);\r
+\r
+   _sizing_eval(obj);\r
+   return obj;\r
+}\r
+\r
+\r
+/**\r
+ * This Get's the entry object of Autocompleteview object.\r
+ *\r
+ * @param obj The Autocompleteview object.\r
+ * @return the entry object.\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI Evas_Object *\r
+elm_autocompleteview_entry_get(Evas_Object *obj)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(!wd) return NULL;\r
+\r
+   return wd->entry;\r
+}\r
+\r
+/**\r
+ * This Get's the editfield object of the Autocompleteview object.\r
+ *\r
+ * @param obj The Autocompleteview object.\r
+ * @return The Editfield object.\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI Evas_Object *\r
+elm_autocompleteview_editfield_get(Evas_Object *obj)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(!wd) return NULL;\r
+\r
+   return wd->editfield;\r
+}\r
+\r
+\r
+/**\r
+ * This Specifies the minimum number of characters the user has to type in the editfield \r
+ * before the drop down list is shown.When threshold is less than or equals 0, a threshold of 1 is applied by default.\r
+ *\r
+ * @param obj The Autocompleteview object\r
+ * @param threshold the number of characters to type before the drop down is shown\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI void\r
+elm_autocompleteview_threshold_set(Evas_Object *obj, int threshold)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(!wd) return;\r
+\r
+   if(threshold <=0)\r
+     {\r
+        wd->threshold = 1;\r
+     }\r
+   else\r
+     {\r
+        wd->threshold = threshold;\r
+     }\r
+}\r
+\r
+\r
+/**\r
+ * This Returns the number of characters the user must type before the drop down list is shown.\r
+ *\r
+ * @param obj The Autocompleteview object.\r
+ * @return The threshold value.\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI int\r
+elm_autocompleteview_threshold_get(Evas_Object *obj)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(!wd) return -1;\r
+\r
+   return wd->threshold;\r
+}\r
+\r
+\r
+/**\r
+ * This Specifies the list of strings which has to be searched to get the list of completion strings.\r
+ *\r
+ * @param obj The Autocompleteview object\r
+ * @param data_list the list of static strings, which has to be searched to get the completion strings.\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI void\r
+elm_autocompleteview_data_set(Evas_Object *obj, Eina_List *data_list)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(!wd) return;\r
+\r
+   wd->data_list = data_list;\r
+\r
+   /*storing sorted list*/\r
+   wd->data_list = eina_list_sort(wd->data_list, eina_list_count(wd->data_list), EINA_COMPARE_CB(_eina_cmp_str));\r
+}\r
+\r
+\r
+/**\r
+ * This Registers the callback function that would be called whenever text is entered in to the entry.\r
+ *\r
+ * @param obj The Autocompleteview object\r
+ * @param elmautocompleteview_matchfunction completion function which list's the completion strings.\r
+ * @param data userdata that would be passed whenever the callback function is called.\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI void\r
+elm_autocompleteview_match_func_set(Evas_Object *obj, elmautocompleteview_matchfunction func,void *data)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(!wd) return;\r
+\r
+   wd->func = func;\r
+   wd->data = data;\r
+}\r
+\r
+/**\r
+ * This updates the text in to autocomplete view.\r
+ *\r
+ * @param obj The Autocompleteview object\r
+ * @param text the text to be updated in to the entry of autocompleteview.\r
+ *\r
+ * @ingroup Autocompleteview\r
+ */\r
+EAPI void\r
+elm_autocompleteview_text_update(Evas_Object *obj, char *text)\r
+{\r
+   Widget_Data *wd = elm_widget_data_get(obj);\r
+   if(!wd) return;\r
+\r
+   if(text!=NULL)\r
+     {\r
+        elm_entry_entry_set(wd->entry, text);\r
+        elm_entry_cursor_end_set(wd->entry);\r
+        wd->text_set =  EINA_TRUE;\r
+     }\r
+}\r
diff --git a/src/lib/elm_carousel.c b/src/lib/elm_carousel.c
new file mode 100644 (file)
index 0000000..dff4e3e
--- /dev/null
@@ -0,0 +1,257 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+#include "els_scroller.h"
+
+// FIXME: this is NOT the carousel - yet!
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *scr, *bx;
+   Eina_List *items;
+   int icon_size;
+};
+
+struct _Elm_Carousel_Item
+{
+   Evas_Object *obj, *base, *icon;
+   const char *label;
+   Evas_Smart_Cb func;
+   const void *data;
+   Eina_Bool selected : 1;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+
+static void
+_item_show(Elm_Carousel_Item *it)
+{
+   Widget_Data *wd = elm_widget_data_get(it->obj);
+   Evas_Coord x, y, w, h, bx, by;
+   if (!wd) return;
+   evas_object_geometry_get(wd->bx, &bx, &by, NULL, NULL);
+   evas_object_geometry_get(it->base, &x, &y, &w, &h);
+   elm_smart_scroller_child_region_show(wd->scr, x - bx, y - by, w, h);
+}
+
+static void
+_item_select(Elm_Carousel_Item *it)
+{
+   Elm_Carousel_Item *it2;
+   Widget_Data *wd = elm_widget_data_get(it->obj);
+   Evas_Object *obj2;
+   const Eina_List *l;
+   if (!wd) return;
+   if (it->selected) return;
+   EINA_LIST_FOREACH(wd->items, l, it2)
+     {
+       if (it2->selected)
+         {
+            it2->selected = EINA_FALSE;
+            edje_object_signal_emit(it2->base, "elm,state,unselected", "elm");
+            break;
+         }
+     }
+   it->selected = EINA_TRUE;
+   edje_object_signal_emit(it->base, "elm,state,selected", "elm");
+   _item_show(it);
+   obj2 = it->obj;
+   if (it->func) it->func((void *)(it->data), it->obj, it);
+   evas_object_smart_callback_call(obj2, "clicked", it);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Eina_List *l;
+   const Elm_Carousel_Item *it;
+   if (!wd) return;
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+        Evas_Coord mw, mh;
+
+       if (it->selected)
+         edje_object_signal_emit(it->base, "elm,state,selected", "elm");
+       _elm_theme_object_set(obj, it->base, "carousel", "item", elm_widget_style_get(obj));
+       edje_object_scale_set(it->base, elm_widget_scale_get(obj) * _elm_config->scale);
+       if (it->icon)
+         {
+            edje_extern_object_min_size_set(it->icon,
+                                            (double)wd->icon_size * _elm_config->scale,
+                                            (double)wd->icon_size * _elm_config->scale);
+            edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon);
+         }
+       edje_object_part_text_set(it->base, "elm.text", it->label);
+       edje_object_size_min_calc(it->base, &mw, &mh);
+       evas_object_size_hint_min_set(it->base, mw, mh);
+       evas_object_size_hint_max_set(it->base, 9999, mh);
+     }
+   _sizing_eval(obj);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+   Evas_Coord vw = 0, vh = 0;
+   if (!wd) return;
+   edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
+   evas_object_resize(wd->scr, 500, 500);
+   evas_object_size_hint_min_get(wd->bx, &minw, &minh);
+   evas_object_resize(wd->bx, minw, minh);
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
+   minw = minw + (500 - vw);
+   minh = minh + (500 - vh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord mw, mh, vw, vh, w, h;
+   const Eina_List *l;
+   Elm_Carousel_Item *it;
+   if (!wd) return;
+   elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
+   evas_object_size_hint_min_get(wd->bx, &mw, &mh);
+   evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h);
+   if (vw >= mw)
+     {
+       if (w != vw) evas_object_resize(wd->bx, vw, h);
+     }
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+       if (it->selected)
+         {
+            _item_show(it);
+            break;
+         }
+     }
+
+}
+
+static void
+_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
+{
+   _item_select(data);
+}
+
+EAPI Evas_Object *
+elm_carousel_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "carousel");
+   elm_widget_type_set(obj, "carousel");
+   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);
+
+   wd->scr = elm_smart_scroller_add(e);
+   elm_smart_scroller_widget_set(wd->scr, obj);
+   elm_smart_scroller_object_theme_set(obj, wd->scr, "carousel", "base", "default");
+   elm_widget_resize_object_set(obj, wd->scr);
+   elm_smart_scroller_policy_set(wd->scr,
+                                ELM_SMART_SCROLLER_POLICY_AUTO,
+                                ELM_SMART_SCROLLER_POLICY_OFF);
+
+   wd->icon_size = 32;
+
+   wd->bx = evas_object_box_add(e);
+   evas_object_box_layout_set(wd->bx,
+                  evas_object_box_layout_homogeneous_horizontal, NULL, NULL);
+   elm_widget_sub_object_add(obj, wd->bx);
+   elm_smart_scroller_child_set(wd->scr, wd->bx);
+   evas_object_show(wd->bx);
+
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
+                                 _resize, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+EAPI Elm_Carousel_Item *
+elm_carousel_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, Evas_Smart_Cb func, const void *data)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   Evas_Coord mw, mh;
+   Elm_Carousel_Item *it = calloc(1, sizeof(Elm_Carousel_Item));
+
+   if (!it) return NULL;
+   wd->items = eina_list_append(wd->items, it);
+   it->obj = obj;
+   it->label = eina_stringshare_add(label);
+   it->icon = icon;
+   it->func = func;
+   it->data = data;
+   it->base = edje_object_add(evas_object_evas_get(obj));
+   _elm_theme_object_set(obj, it->base, "carousel", "item", elm_widget_style_get(obj));
+   edje_object_signal_callback_add(it->base, "elm,action,click", "elm",
+                                  _select, it);
+   elm_widget_sub_object_add(obj, it->base);
+   if (it->icon)
+     {
+       edje_extern_object_min_size_set(it->icon,
+                                       (double)wd->icon_size * _elm_config->scale,
+                                       (double)wd->icon_size * _elm_config->scale);
+       edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon);
+       evas_object_show(it->icon);
+       elm_widget_sub_object_add(obj, it->icon);
+     }
+   edje_object_part_text_set(it->base, "elm.text", it->label);
+   edje_object_size_min_calc(it->base, &mw, &mh);
+   evas_object_size_hint_weight_set(it->base, 0.0, 0.0);
+   evas_object_size_hint_align_set(it->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_min_set(it->base, mw, mh);
+   evas_object_size_hint_max_set(it->base, 9999, mh);
+   evas_object_box_append(wd->bx, it->base);
+   evas_object_show(it->base);
+   _sizing_eval(obj);
+   return it;
+}
+
+EAPI void
+elm_carousel_item_del(Elm_Carousel_Item *it)
+{
+   Widget_Data *wd = elm_widget_data_get(it->obj);
+   Evas_Object *obj2 = it->obj;
+   if (!wd) return;
+   wd->items = eina_list_remove(wd->items, it);
+   eina_stringshare_del(it->label);
+   if (it->icon) evas_object_del(it->icon);
+   evas_object_del(it->base);
+   free(it);
+   _theme_hook(obj2);
+}
+
+EAPI void
+elm_carousel_item_select(Elm_Carousel_Item *item)
+{
+   _item_select(item);
+}
diff --git a/src/lib/elm_datepicker.c b/src/lib/elm_datepicker.c
new file mode 100644 (file)
index 0000000..2347de8
--- /dev/null
@@ -0,0 +1,611 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+#include <langinfo.h>
+#include <string.h>
+
+/**
+ * @defgroup Datepicker Datepicker
+ * @ingroup Elementary
+ *
+ * This is a date picker.
+ */
+
+enum {
+       PICKER_YEAR,
+       PICKER_MON,
+       PICKER_DAY,
+       PICKER_MAX
+};
+
+#define YEAR_MIN (1900)
+#define YEAR_MAX (2099)
+#define MONTH_MIN (1)
+#define MONTH_MAX (12)
+#define DAY_MIN (1)
+#define DAY_MAX (31)
+#define MONTH_MAX (12)
+#define DAY_MAX (31)
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data {
+       Evas_Object *base;
+       Evas_Object *pickers[PICKER_MAX];
+       int y_max, m_max, d_max;
+       int y_min, m_min, d_min;
+       int day_of_month;
+       int year, month, day;
+       char fmt[8];
+};
+
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _disable_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _i18n(Evas_Object *obj);
+static Evas_Object *_picker_add(Evas_Object *ly, const char *part, int min, int max, const char *fmt);
+static void _pickers_del(Evas_Object *obj);
+static void _picker_item_add(Evas_Object *eo, int min, int max, const char *fmt);
+static void _picker_item_del(Evas_Object *eo);
+static void _update_day_of_month(Evas_Object *obj, int month);
+static void _update_picker(Evas_Object *picker, int nth);
+static void _changed(Evas_Object *picker, Evas_Object *child, Evas_Object *obj);
+static void _overflow_cb(void *data, Evas_Object *obj, void *event_info);
+static void _underflow_cb(void *data, Evas_Object *obj, void *event_info);
+static void _year_changed_cb(void *data, Evas_Object *obj, void *event_info);
+static void _month_changed_cb(void *data, Evas_Object *obj, void *event_info);
+static void _day_changed_cb(void *data, Evas_Object *obj, void *event_info);
+static void _pickers_add(Evas_Object *obj);
+static void _callback_init(Evas_Object *obj);
+
+static Eina_Bool
+_is_valid_date(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       int cur, min, max;
+       if (!wd) return EINA_FALSE;
+
+       cur = wd->year * 10000 + wd->month * 100 + wd->day;
+       max = wd->y_max * 10000 + wd->m_max * 100 + wd->d_max;
+       min = wd->y_min * 10000 + wd->m_min * 100 + wd->d_min;
+
+       if (cur > max || cur < min) return EINA_FALSE;
+       return EINA_TRUE;
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       _pickers_del(obj);
+       free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       _pickers_del(obj);
+       _elm_theme_object_set(obj, wd->base, "datepicker", "base", elm_widget_style_get(obj));
+       _pickers_add(obj);
+       _i18n(obj);
+
+       _update_picker(wd->pickers[PICKER_YEAR], wd->year - wd->y_min);
+       _update_picker(wd->pickers[PICKER_MON], wd->month - 1);
+       _update_picker(wd->pickers[PICKER_DAY], wd->day - 1);
+
+       _sizing_eval(obj);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+
+       if (!wd) return;
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       evas_object_size_hint_min_set(obj, minw, minh);
+       evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_i18n(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       const char *fmt;
+       char sig[32] = { "elm,state," };
+       int i = 0, j, k;
+
+       if (!wd) return;
+
+       j = strlen(sig);
+       k = j;
+       fmt = nl_langinfo(D_FMT);
+
+       while (fmt[i] && j < 32) {
+               if (fmt[i] == '%' && fmt[i+1]) {
+                       i++;
+                       switch (fmt[i]) {
+                       case 'Y': case 'M': case 'D': case 'y': case 'm': case 'd':
+                               sig[j++] = tolower(fmt[i]);
+                               sig[j++] = tolower(fmt[i]);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               i++;
+       }
+       sig[j] = '\0';
+       edje_object_signal_emit(wd->base, sig, "elm");
+       snprintf(wd->fmt, 8, sig + k);
+}
+
+static void
+_picker_item_add(Evas_Object *eo, int min, int max, const char *fmt)
+{
+       char buf[8];
+       for (; min <= max; min++) {
+               snprintf(buf, 8, fmt, min);
+               elm_picker_item_append(eo, buf, NULL, NULL);
+       }
+}
+
+static void
+_picker_item_del(Evas_Object *eo)
+{
+       Elm_Picker_Item *item;
+       item = elm_picker_first_item_get(eo);
+       while (item) {
+               elm_picker_item_del(item);
+               item = elm_picker_first_item_get(eo);
+       }
+}
+
+static Evas_Object *
+_picker_add(Evas_Object *ly, const char *part, int min, int max, const char *fmt)
+{
+       Evas_Object *eo;
+       eo = elm_picker_add(ly);
+       _picker_item_add(eo, min, max, fmt);
+       if (part)
+               edje_object_part_swallow(ly, part, eo);
+       return eo;
+}
+
+static void
+_update_day_of_month(Evas_Object *obj, int month)
+{
+       int tmp;
+       Elm_Picker_Item *item;
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       tmp = wd->day_of_month;
+       switch (month) {
+       case 4: case 6: case 9: case 11:
+               wd->day_of_month = 30;
+               break;
+       case 2:
+               if ((!(wd->year % 4) && (wd->year % 100)) || !(wd->year % 400))
+                       wd->day_of_month = 29;
+               else
+                       wd->day_of_month = 28;
+               break;
+       default:
+               wd->day_of_month = 31;
+               break;
+       }
+
+       if (wd->day > wd->day_of_month) {
+               wd->day = wd->day_of_month;
+       }
+
+       if (tmp == wd->day_of_month) return;
+       if (tmp > wd->day_of_month) {
+               for (; tmp > wd->day_of_month; tmp--) {
+                       item = elm_picker_last_item_get(wd->pickers[PICKER_DAY]);
+                       elm_picker_item_del(item);
+               }
+       } else {
+               char buf[8];
+               tmp++;
+               for (; tmp <= wd->day_of_month; tmp++) {
+                       snprintf(buf, 8, "%2d", tmp);
+                       elm_picker_item_append(wd->pickers[PICKER_DAY], buf, NULL, NULL);
+               }
+       }
+}
+
+static void
+_update_picker(Evas_Object *picker, int nth)
+{
+       const Eina_List *l;
+       Elm_Picker_Item *item;
+       int i;
+       l = elm_picker_items_get(picker);
+       for (i = 0; i < nth; i++) {
+               l = l->next;
+               if (!l) break;
+       }
+       item = eina_list_data_get(l);
+       elm_picker_item_selected_set(item);
+}
+
+static void
+_changed(Evas_Object *picker, Evas_Object *child, Evas_Object *obj)
+{
+       int c1, c2 = 0;
+       c1 = (int)(evas_object_data_get(picker, "carryon"));
+       evas_object_data_set(picker, "carryon", (void *)0);
+
+       if (child) {
+               c2 = (int)(evas_object_data_get(child, "carryon"));
+               evas_object_data_set(child, "carryon", (void *)0);
+       }
+
+       if (!c1 && !c2)
+               evas_object_smart_callback_call(obj, "changed", NULL);
+}
+
+static void
+_overflow_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       Evas_Object *eo;
+       eo = evas_object_data_get(obj, "parent");
+       if (eo) {
+               elm_picker_next(eo);
+               evas_object_data_set(obj, "carryon", (void *)1);
+       }
+}
+
+static void
+_underflow_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       Evas_Object *eo;
+       eo = evas_object_data_get(obj, "parent");
+       Widget_Data *wd = elm_widget_data_get(data);
+
+       if (eo) {
+               elm_picker_prev(eo);
+               evas_object_data_set(obj, "carryon", (void *)-1);
+       }
+
+       if (obj == wd->pickers[PICKER_DAY]) {
+               Elm_Picker_Item *item;
+               _update_day_of_month(data, wd->month - 1);
+               wd->day = wd->day_of_month;
+               item = elm_picker_last_item_get(obj);
+               elm_picker_item_selected_set(item);
+       }
+}
+
+static void
+_year_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       const char *year;
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Object *child;
+       if (!wd) return;
+
+       year = elm_picker_item_label_get(event_info);
+       wd->year = atoi(year);
+
+       if (wd->month == 2)
+               _update_day_of_month(data, wd->month);
+       child = evas_object_data_get(obj, "child");
+       _changed(obj, child, data);
+}
+
+static void
+_month_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       const char *month;
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Object *child;
+       if (!wd) return;
+
+       month = elm_picker_item_label_get(event_info);
+       wd->month = atoi(month);
+
+       _update_day_of_month(data, wd->month);
+       child = evas_object_data_get(obj, "child");
+       _changed(obj, child, data);
+}
+
+static void
+_day_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       const char *day;
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Object *child;
+       if (!wd) return;
+
+       day = elm_picker_item_label_get(event_info);
+       wd->day = atoi(day);
+
+       child = evas_object_data_get(obj, "child");
+       _changed(obj, child, data);
+}
+
+static void
+_pickers_add(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       wd->pickers[PICKER_YEAR] = _picker_add(wd->base, "elm.swallow.year", wd->y_min, wd->y_max, "%04d");
+       wd->pickers[PICKER_MON] = _picker_add(wd->base, "elm.swallow.mon", 1, 12, "%d");
+       wd->pickers[PICKER_DAY] = _picker_add(wd->base, "elm.swallow.day", 1, wd->day_of_month, "%02d");
+       _callback_init(obj);
+}
+
+static void
+_pickers_del(Evas_Object *obj)
+{
+       int i = 0;
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       for (i = 0; i < PICKER_MAX; i++) {
+               if (wd->pickers[i]) {
+                       evas_object_del(wd->pickers[i]);
+                       wd->pickers[i] = NULL;
+               }
+       }
+}
+
+static void
+_callback_init(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       evas_object_data_set(wd->pickers[PICKER_YEAR], "child", wd->pickers[PICKER_MON]);
+       evas_object_data_set(wd->pickers[PICKER_MON], "child", wd->pickers[PICKER_DAY]);
+       evas_object_data_set(wd->pickers[PICKER_MON], "parent", wd->pickers[PICKER_YEAR]);
+       evas_object_data_set(wd->pickers[PICKER_DAY], "parent", wd->pickers[PICKER_MON]);
+
+       evas_object_smart_callback_add(wd->pickers[PICKER_MON], "overflowed", _overflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_MON], "underflowed", _underflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_DAY], "overflowed", _overflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_DAY], "underflowed", _underflow_cb, obj);
+
+       evas_object_smart_callback_add(wd->pickers[PICKER_YEAR], "changed", _year_changed_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_MON], "changed", _month_changed_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_DAY], "changed", _day_changed_cb, obj);
+}
+
+/**
+ * Add a new datepicker to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Datepicker
+ */
+EAPI Evas_Object *
+elm_datepicker_add(Evas_Object *parent)
+{
+       Evas_Object *obj;
+       Evas *e;
+       Widget_Data *wd;
+
+       wd = ELM_NEW(Widget_Data);
+       e = evas_object_evas_get(parent);
+       obj = elm_widget_add(e);
+       elm_widget_type_set(obj, "datepicker");
+       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_disable_hook_set(obj, _disable_hook);
+
+       wd->base = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->base, "datepicker", "base", "default");
+       elm_widget_resize_object_set(obj, wd->base);
+
+       wd->y_max = YEAR_MAX;
+       wd->y_min = YEAR_MIN;
+       wd->m_max = MONTH_MAX;
+       wd->m_min = MONTH_MIN;
+       wd->d_min = DAY_MIN;
+       wd->d_max = DAY_MAX;
+       wd->day_of_month = DAY_MAX;
+
+       wd->year = YEAR_MIN;
+       wd->month = 1;
+       wd->day = 1;
+
+       _pickers_add(obj);
+
+       _i18n(obj);
+
+       _sizing_eval(obj);
+       return obj;
+}
+
+/**
+ * Set selected date of the datepicker
+ *
+ * @param obj The datepicker object
+ * @param year The year to set
+ * @param month The month to set
+ * @param day The day to set
+ *
+ * @ingroup Datepicker
+ */
+EAPI void
+elm_datepicker_date_set(Evas_Object *obj, int year, int month, int day)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       if (year < wd->y_min || year > wd->y_max
+                       || month < 1 || month > 12
+                       || day < 1 || day > 31)
+               return;
+       wd->year = year;
+       wd->month = month;
+       wd->day = day;
+       _update_day_of_month(obj, month);
+       _update_picker(wd->pickers[PICKER_YEAR], wd->year - wd->y_min);
+       _update_picker(wd->pickers[PICKER_MON], wd->month - 1);
+       _update_picker(wd->pickers[PICKER_DAY], wd->day - 1);
+}
+
+/**
+ * Get selected date of the datepicker
+ *
+ * @param obj The datepicker object
+ * @param year The pointer to the variable get the selected year
+ * @param month The pointer to the variable get the selected month
+ * @param day The pointer to the variable get the selected day
+ *
+ * @ingroup Datepicker
+ */
+EAPI void
+elm_datepicker_date_get(const Evas_Object *obj, int *year, int *month, int *day)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       if (year)
+               *year = wd->year;
+       if (month)
+               *month = wd->month;
+       if (day)
+               *day = wd->day;
+}
+
+/**
+ * Set upper bound of the datepicker
+ *
+ * @param obj The datepicker object
+ * @param year The year to set
+ * @param month The month to set
+ * @param day The day to set
+ *
+ * @ingroup Datepicker
+ */
+EAPI void
+elm_datepicker_date_min_set(Evas_Object *obj, int year, int month, int day)
+{
+       // TODO
+}
+
+/**
+ * Get lower bound of the datepicker
+ *
+ * @param obj The datepicker object
+ * @param year The pointer to the variable get the minimum year
+ * @param month The pointer to the variable get the minimum month
+ * @param day The pointer to the variable get the minimum day
+ *
+ * @ingroup Datepicker
+ */
+EAPI void
+elm_datepicker_date_min_get(const Evas_Object *obj, int *year, int *month, int *day)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       if (year)
+               *year = wd->y_min;
+       if (month)
+               *month = wd->m_min;
+       if (day)
+               *day = wd->d_min;
+}
+
+/**
+ * Set lower bound of the datepicker
+ *
+ * @param obj The datepicker object
+ * @param year The year to set
+ * @param month The month to set
+ * @param day The day to set
+ *
+ * @ingroup Datepicker
+ */
+EAPI void
+elm_datepicker_date_max_set(Evas_Object *obj, int year, int month, int day)
+{
+       // TODO
+}
+
+/**
+ * Get upper bound of the datepicker
+ *
+ * @param obj The datepicker object
+ * @param year The pointer to the variable get the maximum year
+ * @param month The pointer to the variable get the maximum month
+ * @param day The pointer to the variable get the maximum day
+ *
+ * @ingroup Datepicker
+ */
+EAPI void
+elm_datepicker_date_max_get(const Evas_Object *obj, int *year, int *month, int *day)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       if (year)
+               *year = wd->y_max;
+       if (month)
+               *month = wd->m_max;
+       if (day)
+               *day = wd->d_max;
+}
+
+/**
+ * Set date format of datepicker
+ *
+ * @param obj The datepicker object
+ * @param fmt The date format, ex) yymmdd
+ *
+ * @ingroup Datepicker
+ */
+EAPI void
+elm_datepicker_date_format_set(Evas_Object *obj, const char *fmt)
+{
+       int i;
+       char sig[32];
+       Widget_Data *wd = elm_widget_data_get(obj);
+
+       if (!wd || !fmt) return;
+
+       for (i = 0; i < sizeof(wd->fmt); i++) {
+               if (!fmt[i]) break;
+               wd->fmt[i] = tolower(fmt[i]);
+       }
+       wd->fmt[i] = '\0';
+
+       snprintf(sig, 32, "elm,state,%s", wd->fmt);
+
+       edje_object_signal_emit(wd->base, sig, "elm");
+}
+
+/**
+ * Get date format of datepicker
+ *
+ * @param obj The datepicker object
+ * @return The date format of given datepicker
+ *
+ * @ingroup Datepicker
+ */
+EAPI const char *
+elm_datepicker_date_format_get(const Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return NULL;
+       return  wd->fmt;
+}
diff --git a/src/lib/elm_gallery.c b/src/lib/elm_gallery.c
new file mode 100644 (file)
index 0000000..81e6532
--- /dev/null
@@ -0,0 +1,1065 @@
+/**\r
+  *\r
+  * @defgroup Gallery\r
+  * @ingroup Elementary\r
+  *\r
+  * This is an gallery.\r
+  *\r
+  */\r
+\r
+\r
+#include <Elementary.h>\r
+#include "elm_priv.h"\r
+\r
+\r
+#define INIT_ITEM_NUM          (2)\r
+#define GROUP_ITEM_NUM         (3)\r
+#define PADDING_WIDTH          (25)\r
+\r
+#define MULTI_TOUCH_SET        (1)\r
+\r
+#define DEFAULT_STATUS       0\r
+#define TRAN_STATUS             1\r
+#define WHITE_DIM_STATUS   2\r
+\r
+typedef struct Widget_Data {\r
+       Evas_Object *obj;       \r
+       Evas_Object *sc;\r
+       Evas_Object *tb;\r
+       Evas_Object *rect;\r
+       const char *widget_name;\r
+       int init_num;\r
+       int padding_w;\r
+       Eina_List *list;\r
+       Ecore_Idler *eidler;    \r
+       Evas_Coord x, y, w, h;\r
+       int prex;       \r
+       int item_type;\r
+       int item_count;\r
+} Widget_Data;\r
+\r
+static void gallery_add(Evas_Object *obj);\r
+static void gallery_del(Evas_Object *obj);\r
+static void gallery_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);\r
+static void gallery_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);\r
+static void gallery_show(Evas_Object *obj);\r
+static void gallery_hide(Evas_Object *obj);\r
+static void gallery_color_set(Evas_Object *obj, int r, int g, int b, int a);\r
+static void gallery_clip_set(Evas_Object *obj, Evas_Object *clip);\r
+static void gallery_clip_unset(Evas_Object *obj);\r
+static Evas_Smart *gallery_smart_get(void);\r
+static Evas_Object *gallery_new(Evas_Object *parent);\r
+static void _update_gallery(Evas_Object *obj);\r
+static void _resize_gallery(Evas_Object *obj);\r
+static void _gallery_scroller_cb(void *data, Evas_Object *obj, void *event_info);\r
+static void _gallery_animate_stop_cb(void *data, Evas_Object *obj, void *event_info);\r
+static void _gallery_move_right_cb(Evas_Object *obj, int index);\r
+static void _gallery_move_left_cb(Evas_Object *obj, int index);\r
+static void _gallery_clear_all_image(Evas_Object *obj);\r
+static void _gallery_add_image(Evas_Object *obj, int index, void *data);\r
+static void _gallery_del_image(void *data);\r
+static void _gallery_del_image_force(void *data);\r
+static Eina_Bool _gallery_idle_handler_cb(void* data);\r
+static void _gallery_auto_blight(Evas_Object *obj);\r
+static void _gallery_set_all_status(Evas_Object *obj,int status);\r
+\r
+       \r
+static void gallery_add(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       wd = (Widget_Data *)calloc(1, sizeof(Widget_Data));\r
+       if (!wd) {\r
+               errno = ENOMEM;\r
+       } else {\r
+               evas_object_smart_data_set(obj, wd);\r
+                       \r
+               wd->sc = elm_scroller_add(obj);\r
+               evas_object_size_hint_weight_set(wd->sc, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
+               elm_scroller_bounce_set(wd->sc, 1, 0);\r
+               elm_scroller_policy_set(wd->sc, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);\r
+               evas_object_smart_callback_add(wd->sc, "scroll", _gallery_scroller_cb, wd);\r
+               evas_object_smart_callback_add(wd->sc, "scroll,anim,stop", _gallery_animate_stop_cb, wd);\r
+               \r
+               wd->tb = elm_table_add(obj);\r
+               evas_object_size_hint_weight_set(wd->tb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
+               evas_object_size_hint_align_set(wd->tb, EVAS_HINT_FILL, EVAS_HINT_FILL);\r
+               elm_scroller_content_set(wd->sc, wd->tb);\r
+\r
+               wd->widget_name = eina_stringshare_add("gallery");\r
+               wd->init_num = INIT_ITEM_NUM;\r
+               wd->obj = obj;\r
+               wd->eidler = NULL;\r
+               wd->padding_w = PADDING_WIDTH;\r
+               wd->item_type =  DEFAULT_STATUS;\r
+               wd->item_count = GROUP_ITEM_NUM;\r
+       }\r
+}\r
+\r
+static void gallery_del(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+\r
+       if(wd->eidler){\r
+               ecore_idler_del(wd->eidler);\r
+               wd->eidler = NULL;\r
+       }\r
+       \r
+       if(wd->sc){\r
+               evas_object_del(wd->sc);\r
+               wd->sc = NULL;\r
+       }\r
+       \r
+       if(wd->list){\r
+               eina_list_free(wd->list);\r
+               wd->list = NULL;\r
+       }\r
+       \r
+       if(wd) free(wd);\r
+}\r
+\r
+static void gallery_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       wd->x = x;\r
+       wd->y = y;\r
+       evas_object_move(wd->sc, x, y);\r
+}\r
+\r
+static void gallery_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       wd->w = w;\r
+       wd->h = h;\r
+               \r
+       evas_object_resize(wd->sc, w, h);       \r
+\r
+       wd->padding_w = (w - ((w-2)/(wd->item_count +1))*wd->item_count )/4;\r
+\r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+       {\r
+               elm_table_padding_set(wd->tb, wd->padding_w, 0);\r
+               elm_scroller_page_size_set(wd->sc, (wd->w -2)/(wd->item_count +1) + wd->padding_w, wd->h);\r
+       }\r
+       else\r
+       {\r
+               elm_table_padding_set(wd->tb, 0, 0);\r
+               elm_scroller_page_size_set(wd->sc, (wd->w)/(wd->item_count ) , wd->h);\r
+       }\r
+       _resize_gallery(obj);\r
+       _update_gallery(obj);   \r
+}\r
+\r
+static void gallery_show(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       evas_object_show(wd->tb);       \r
+       evas_object_show(wd->sc);       \r
\r
+       _update_gallery(obj);   \r
+\r
+       if(wd->eidler){\r
+               ecore_idler_del(wd->eidler);\r
+               wd->eidler = NULL;\r
+       }\r
+       \r
+       wd->eidler = ecore_idler_add(_gallery_idle_handler_cb, wd);             \r
+}\r
+\r
+static void gallery_hide(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+       _gallery_clear_all_image(obj);  \r
+       evas_object_hide(wd->sc);\r
+}\r
+\r
+static void gallery_color_set(Evas_Object *obj, int r, int g, int b, int a)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+       evas_object_color_set(wd->sc, r, g, b, a);\r
+}\r
+\r
+\r
+static void gallery_clip_set(Evas_Object *obj, Evas_Object *clip)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+       evas_object_clip_set(wd->sc, clip);\r
+}\r
+\r
+static void gallery_clip_unset(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+       evas_object_clip_unset(wd->sc);\r
+\r
+}\r
+\r
+static Evas_Smart *gallery_smart_get(void)\r
+{\r
+       static Evas_Smart *s = NULL;\r
+       static Evas_Smart_Class sc = EVAS_SMART_CLASS_INIT_NAME_VERSION("UI_gallery");\r
+\r
+       if (!s) {\r
+               sc.add = gallery_add;\r
+               sc.del = gallery_del;\r
+               sc.move = gallery_move;\r
+               sc.resize = gallery_resize;\r
+               sc.show = gallery_show;\r
+               sc.hide = gallery_hide;\r
+               sc.color_set = gallery_color_set;\r
+               sc.clip_set = gallery_clip_set;\r
+               sc.clip_unset = gallery_clip_unset;\r
+               s = evas_smart_class_new(&sc);\r
+       }\r
+\r
+       return s;\r
+}\r
+\r
+static Evas_Object *gallery_new(Evas_Object *parent)\r
+{\r
+       Evas_Object *obj;\r
+       Evas *e;\r
+       e = evas_object_evas_get(parent);\r
+       if (!e) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       } else {\r
+               obj = evas_object_smart_add(e, gallery_smart_get());\r
+       }\r
+       return obj;\r
+}\r
+\r
+static void _gallery_scroller_cb(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       Evas_Coord ix, iy, iw, ih;\r
+\r
+       elm_scroller_region_get(obj, &ix, &iy, &iw, &ih);\r
+\r
+       int index;\r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+       {                       \r
+                index = ix/((wd->w -2)/(wd->item_count +1)  + wd->padding_w);\r
+       }\r
+       else\r
+       {\r
+                index = ix/((wd->w)/(wd->item_count ) );\r
+       }\r
+\r
+       printf("scroller %d\n",index);\r
+       \r
+       if(wd->prex < ix){\r
+               _gallery_move_right_cb(wd->obj, index);\r
+       }else\r
+               _gallery_move_left_cb(wd->obj, index);\r
+\r
+       wd->prex = ix;\r
+\r
+       if(wd->item_type == WHITE_DIM_STATUS )\r
+       {\r
+               _gallery_auto_blight(wd->obj);\r
+               printf("scroller blight\n");\r
+       }\r
+}\r
+\r
+static Eina_Bool _gallery_idle_handler_cb(void* data)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       Elm_Gallery_Item *it = NULL;\r
+       Evas_Coord ix, iy, iw, ih;\r
\r
+       elm_scroller_region_get(wd->sc, &ix, &iy, &iw, &ih);\r
+\r
+       int index;\r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+       {\r
+                index = ix/((wd->w -2)/(wd->item_count +1)  + wd->padding_w);\r
+       }\r
+       else\r
+       {\r
+                index = ix/((wd->w )/(wd->item_count ));\r
+       }\r
+       \r
+       it = (Elm_Gallery_Item *)eina_list_nth(wd->list, index +2);\r
+       \r
+       if(it != NULL){\r
+               evas_object_smart_callback_call(wd->obj, "select", it);\r
+       }\r
+\r
+       if(wd->eidler){\r
+               ecore_idler_del(wd->eidler);\r
+               wd->eidler = NULL;\r
+       }\r
+       \r
+       return 0; \r
+}\r
+\r
+static void _gallery_animate_stop_cb(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       if (!wd) return;\r
+       \r
+       if(wd->eidler){\r
+               ecore_idler_del(wd->eidler);\r
+               wd->eidler = NULL;\r
+       }\r
+\r
+       wd->eidler = ecore_idler_add(_gallery_idle_handler_cb, wd);     \r
+}\r
+\r
+static void _resize_gallery(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       int count = 0;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       if(wd->rect){\r
+               elm_table_unpack(wd->tb, wd->rect);\r
+               evas_object_del(wd->rect);\r
+               wd->rect = NULL;\r
+       }\r
+\r
+       count = eina_list_count(wd->list);\r
+\r
+       wd->rect = evas_object_rectangle_add(evas_object_evas_get(obj));\r
+       \r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+               evas_object_size_hint_min_set(wd->rect, ((wd->w -2)/(wd->item_count +1)) *count, 1);\r
+       else evas_object_size_hint_min_set(wd->rect, ((wd->w )/(wd->item_count )) *count, 1);\r
+       \r
+       elm_table_pack(wd->tb, wd->rect, 0, 0, count, 1);       \r
+\r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+       {\r
+               evas_object_size_hint_min_set(wd->tb, ((wd->w -2)/(wd->item_count +1)  + wd->padding_w) *count - wd->padding_w, wd->h -2);\r
+               elm_scroller_content_min_limit(wd->sc, ((wd->w -2)/(wd->item_count +1)  + wd->padding_w) *count - wd->padding_w, wd->h -2);\r
+       }\r
+       else\r
+       {\r
+               evas_object_size_hint_min_set(wd->tb, ((wd->w )/(wd->item_count )  ) *count, wd->h );\r
+               elm_scroller_content_min_limit(wd->sc, ((wd->w )/(wd->item_count ) ) *count , wd->h);\r
+       }\r
+}\r
+\r
+static void gallery_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       Elm_Gallery_Item *it = data;\r
+       Evas_Event_Mouse_Down *ev = event_info;\r
+                       \r
+       if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)\r
+               it->on_hold = EINA_TRUE;\r
+       else \r
+               it->on_hold = EINA_FALSE;\r
+\r
+\r
+       Widget_Data *wd = evas_object_smart_data_get(it->parent);\r
+       if(wd->item_type ==  WHITE_DIM_STATUS)\r
+       {\r
+               edje_object_signal_emit(it->ly, "set_show_red_border", "elm");\r
+       }\r
+\r
+       Evas_Coord ix, iy, iw, ih;              \r
+       Evas_Coord x, y, w, h;\r
+       evas_object_geometry_get(obj, &x, &y, &w, &h);\r
+       elm_scroller_region_get(wd->sc, &ix, &iy, &iw, &ih);\r
+\r
+       int index;\r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+                index = (ix+x)/((wd->w -2)/(wd->item_count +1)  + wd->padding_w);\r
+       else\r
+       {\r
+               index = (ix+x)/((wd->w )/(wd->item_count));     \r
+               \r
+               printf("select find index %d\n",index);\r
+               if(wd->prex < ix){\r
+                       _gallery_move_right_cb(wd->obj, index);\r
+               }else\r
+                       _gallery_move_left_cb(wd->obj, index);\r
+               \r
+               printf("all print point : %d %d %d %d %d %d %d %d\n",x,y,w,h,ix,iy,iw,ih);\r
+               if(index>0)\r
+                       elm_scroller_region_bring_in(wd->sc,(index-1)*iw/(wd->item_count) ,y,w*(wd->item_count),h);\r
+       }\r
+}\r
+\r
+static void gallery_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       Elm_Gallery_Item *it = data;\r
+       Evas_Event_Mouse_Move *ev = event_info;\r
+               \r
+       if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)\r
+       {\r
+               if (!it->on_hold) it->on_hold = EINA_TRUE;\r
+       }\r
+}\r
+\r
+static void gallery_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       Elm_Gallery_Item *it = data;\r
+       Evas_Event_Mouse_Up *ev = event_info;\r
+       Widget_Data *wd = evas_object_smart_data_get(it->parent);\r
+       Evas_Coord x, y, w, h;\r
+       Evas_Coord ix, iy, iw, ih;\r
+       \r
+       if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->on_hold = EINA_TRUE;\r
+               else it->on_hold = EINA_FALSE;\r
+\r
+       if (it->on_hold)\r
+       {\r
+               it->on_hold= EINA_FALSE;\r
+               return;\r
+       }\r
+\r
+       evas_object_geometry_get(obj, &x, &y, &w, &h);\r
+       elm_scroller_region_get(wd->sc, &ix, &iy, &iw, &ih);\r
+\r
+       int index;\r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+                index = (ix+x)/((wd->w -2)/(wd->item_count +1)  + wd->padding_w);\r
+       else  index = (ix+x)/((wd->w )/(wd->item_count));\r
+       \r
+       it = (Elm_Gallery_Item *)eina_list_nth(wd->list, index);\r
+       \r
+       if(it != NULL){\r
+               evas_object_smart_callback_call(wd->obj, "select", it);\r
+       }\r
+       \r
+}\r
+\r
+static void _gallery_add_image(Evas_Object *obj, int index, void *data)\r
+{\r
+       Widget_Data *wd = NULL;\r
+       Evas_Object *ly = NULL;\r
+       Evas_Object *ic = NULL;\r
+       int w, h;\r
+       \r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       Elm_Gallery_Item *it = (Elm_Gallery_Item *)data;\r
+\r
+       ly = edje_object_add(evas_object_evas_get(obj));\r
+       _elm_theme_object_set(obj,ly,  "gallery", "base", "default");\r
+\r
+       evas_object_size_hint_weight_set(ly, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
+       evas_object_show(ly);\r
+               \r
+       ic = evas_object_image_add(evas_object_evas_get(obj));\r
+       if(wd->item_type == WHITE_DIM_STATUS)\r
+               evas_object_image_load_size_set(ic, wd->w/(wd->item_count) , wd->h/(wd->item_count) );\r
+       else evas_object_image_load_size_set(ic, wd->w/(wd->item_count+1) , wd->h/(wd->item_count+1) );\r
+       \r
+       evas_object_image_file_set(ic, it->path, NULL);\r
+       evas_object_image_size_get(ic, &w, &h); \r
+\r
+\r
+       if(w>h){\r
+               evas_object_image_fill_set(ic, 0, 0, (wd->w -2)/(wd->item_count +1), ((wd->w -2)/(wd->item_count +1) )*h/w);\r
+               if(!(wd->item_type == WHITE_DIM_STATUS))\r
+               {\r
+                       evas_object_size_hint_min_set(ly, (wd->w -2)/(wd->item_count+1) , ((wd->w -2)/(wd->item_count+1) )*h/w);\r
+                       evas_object_size_hint_max_set(ly, (wd->w -2)/(wd->item_count+1) , ((wd->w -2)/(wd->item_count+1) )*h/w);\r
+               }\r
+       }else{\r
+               if((wd->h -2)*w/h > (wd->w -2)/(wd->item_count +1)){\r
+                       evas_object_image_fill_set(ic, 0, 0, (wd->w -2)/(wd->item_count +1), ((wd->w -2)/(wd->item_count +1))*(wd->h -2)/((wd->h -2)*w/h));\r
+                       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+                       {\r
+                               evas_object_size_hint_min_set(ly, (wd->w -2)/(wd->item_count+1) , ((wd->w -2)/(wd->item_count+1) )*(wd->h -2 )/((wd->h -2)*w/h));\r
+                               evas_object_size_hint_max_set(ly, (wd->w -2)/(wd->item_count+1) , ((wd->w -2)/(wd->item_count+1) )*(wd->h -2 )/((wd->h -2)*w/h));\r
+                       }\r
+               }else{\r
+                       evas_object_image_fill_set(ic, 0, 0, (wd->h -2)*w/h, wd->h -2);\r
+                       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+                       {\r
+                               evas_object_size_hint_min_set(ly, (wd->h -2)*w/h, wd->h -2);\r
+                               evas_object_size_hint_max_set(ly, (wd->h -2)*w/h, wd->h -2);\r
+                       }\r
+               }\r
+       }\r
+\r
+       if(wd->item_type == WHITE_DIM_STATUS)\r
+       {\r
+               evas_object_size_hint_min_set(ly,  (wd->w )/(wd->item_count ) ,  ((wd->w )/(wd->item_count ) )*h/w);\r
+               evas_object_size_hint_max_set(ly, (wd->w )/(wd->item_count ),  ((wd->w )/(wd->item_count ) )*h/w);\r
+       }\r
+       \r
+       evas_object_image_filled_set(ic, 1);\r
+       edje_object_part_swallow(ly, "contents", ic);\r
+       evas_object_show(ic);                           \r
+\r
+       evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_DOWN, gallery_down_cb, it);\r
+       evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_MOVE, gallery_move_cb, it);\r
+       evas_object_event_callback_add(ic, EVAS_CALLBACK_MOUSE_UP, gallery_up_cb, it);\r
+       \r
+       it->w = (wd->w -2)/(wd->item_count +1) ;\r
+       it->h = ((wd->w -2)/(wd->item_count +1) )*h/w;\r
+\r
+       it->mw = it->w;\r
+       it->mh = it->h;\r
+\r
+       it->on_highquality = EINA_TRUE;\r
+       it->index = index;\r
+       \r
+       elm_table_pack(wd->tb, ly, index, 1, 1, 1);     \r
+\r
+       if(wd->item_type ==  DEFAULT_STATUS)\r
+               edje_object_signal_emit(ly, "set_bg_default", "elm");\r
+       if(wd->item_type ==  TRAN_STATUS)\r
+       {\r
+               edje_object_signal_emit(ly, "set_bg_tran", "elm");\r
+               edje_object_signal_emit(ly, "set_border_hide", "elm");\r
+       }\r
+       else  // WHITE_DIM_STATUS\r
+       {\r
+               edje_object_signal_emit(ly, "set_bg_default", "elm");\r
+       }\r
+\r
+       it->ly = ly;\r
+       it->obj = ic;           \r
+       it->on_show = EINA_TRUE;        \r
+}\r
+\r
+\r
+\r
+\r
+static void _gallery_auto_blight(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       Elm_Gallery_Item *it;\r
+       Eina_List *l;\r
+       Evas_Coord x, y, w, h;\r
+       \r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       int start_pos=-1;\r
+       int end_pos=-1;\r
+       int ret_pos = -1;\r
+       int count=0;\r
+       EINA_LIST_FOREACH(wd->list, l, it) \r
+       {               \r
+               Elm_Gallery_Item *inner_it = (Elm_Gallery_Item *)it;\r
+               \r
+               if(inner_it->obj) \r
+               {\r
+                       evas_object_geometry_get(it->obj, &x, &y, &w, &h);\r
+                       if(!((x+w < 0) || (x > wd->w)))\r
+                       {\r
+                               if(start_pos==-1)\r
+                                       start_pos=count;\r
+                               else end_pos= count;\r
+                       }\r
+               }               \r
+               count++;\r
+       }\r
+\r
+       if(start_pos!=-1)\r
+       {\r
+               if(end_pos!=-1)\r
+               {\r
+                       ret_pos =(start_pos+end_pos)/2;\r
+               }\r
+               else \r
+               {\r
+                       ret_pos =start_pos;\r
+               }\r
+       }\r
+       \r
+       count =0;\r
+       EINA_LIST_FOREACH(wd->list, l, it) \r
+       {\r
+               Elm_Gallery_Item *inner_it = (Elm_Gallery_Item *)it;\r
+               if(inner_it->obj) \r
+               {\r
+                       if(ret_pos==count)\r
+                       {\r
+                               edje_object_signal_emit(inner_it->ly, "set_bg_white", "elm");\r
+                               printf("auto blight select %d start %d end %d \n",ret_pos,start_pos,end_pos);\r
+                       }\r
+                       else \r
+                       {\r
+                               edje_object_signal_emit(inner_it->ly, "set_bg_default", "elm");                         \r
+                               printf("auto nonblight select %d start %d end %d \n",ret_pos,start_pos,end_pos);\r
+                       }\r
+               }\r
+               count++;\r
+       }       \r
+       printf("auto blight\n");                \r
+}\r
+\r
+static void _gallery_set_all_status(Evas_Object *obj,int status)\r
+{\r
+       Widget_Data *wd;\r
+       Elm_Gallery_Item *it;\r
+       Eina_List *l;   \r
+       \r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+       \r
+       EINA_LIST_FOREACH(wd->list, l, it) \r
+       {               \r
+               Elm_Gallery_Item *inner_it = (Elm_Gallery_Item *)it;\r
+               if(status ==  DEFAULT_STATUS)\r
+               {\r
+                       edje_object_signal_emit(inner_it->ly, "set_bg_default", "elm");\r
+               }\r
+               if(status ==  TRAN_STATUS)\r
+               {\r
+                       edje_object_signal_emit(inner_it->ly, "set_bg_tran", "elm");    \r
+                       edje_object_signal_emit(inner_it->ly, "set_border_hide", "elm");        \r
+               }       \r
+       }\r
+       if(status == WHITE_DIM_STATUS)\r
+       {\r
+               _gallery_auto_blight(obj);\r
+               printf("blight\n");\r
+       }       \r
+}\r
+\r
+\r
+static void _gallery_del_image_force(void *data)\r
+{\r
+       Elm_Gallery_Item *it = (Elm_Gallery_Item *)data;\r
+       Widget_Data *wd = evas_object_smart_data_get(it->parent);\r
+       Evas_Coord x, y, w, h;\r
+\r
+       if(it->on_show == EINA_TRUE){\r
+               if(it->obj) {\r
+                       evas_object_geometry_get(it->obj, &x, &y, &w, &h);\r
+\r
+                       elm_table_unpack(wd->tb, it->ly);\r
+                       evas_object_del(it->ly);\r
+                       evas_object_del(it->obj);\r
+                       it->obj = NULL;\r
+                       it->on_show = EINA_FALSE;\r
+               }\r
+       }\r
+       \r
+}\r
+static void _gallery_del_image(void *data)\r
+{\r
+       Elm_Gallery_Item *it = (Elm_Gallery_Item *)data;\r
+       Widget_Data *wd = evas_object_smart_data_get(it->parent);\r
+       Evas_Coord x, y, w, h;\r
+\r
+       if(it->on_show == EINA_TRUE){\r
+               if(it->obj) {\r
+                       evas_object_geometry_get(it->obj, &x, &y, &w, &h);\r
+\r
+                       if((x+w < 0) || (x > wd->w)){\r
+                               elm_table_unpack(wd->tb, it->ly);\r
+                               evas_object_del(it->ly);\r
+                               evas_object_del(it->obj);\r
+                               it->obj = NULL;\r
+                               it->on_show = EINA_FALSE;\r
+                       }\r
+               }\r
+       }\r
+       \r
+}\r
+\r
+static void _gallery_clear_all_image(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       Elm_Gallery_Item *it;\r
+       Eina_List *l;\r
+\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       EINA_LIST_FOREACH(wd->list, l, it) \r
+       {\r
+               _gallery_del_image_force(it);\r
+       }\r
+}\r
+\r
+static void _update_gallery(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       Evas_Coord x, y, w, h;  \r
+       int i = 0;\r
+       int index = 0;\r
+               \r
+       if (!wd) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
\r
+       if((wd->w == 1) && (wd->h == 1)) return;\r
+\r
+       for(i =wd->init_num -3; i< wd->init_num + 4; i++)\r
+       {\r
+               Elm_Gallery_Item *it = NULL;\r
+               it = (Elm_Gallery_Item *)eina_list_nth(wd->list, i);\r
+\r
+               if(it != NULL){\r
+                       if(it->on_show == EINA_FALSE){  \r
+                               _gallery_add_image(obj, i, it);\r
+                       }\r
+               }\r
+       }\r
+\r
+       if(wd->init_num > 2)\r
+               index = wd->init_num -2;\r
+       else\r
+               index = 0;\r
+       \r
+       elm_scroller_region_get(wd->sc, &x, &y, &w, &h);\r
+       if(!(wd->item_type == WHITE_DIM_STATUS))\r
+               elm_scroller_region_show(wd->sc, index*((wd->w -2)/(wd->item_count +1)  +wd->padding_w), y, w, h);      \r
+       else elm_scroller_region_show(wd->sc, index*((wd->w )/(wd->item_count )), y, w, h);     \r
+}\r
+\r
+static void _gallery_move_right_cb(Evas_Object *obj, int index)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       Elm_Gallery_Item *nit = NULL;\r
+\r
+       nit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index + wd->item_count );\r
+       if(nit != NULL){                \r
+               if(nit->on_show == EINA_FALSE){\r
+                       _gallery_add_image(obj, index + wd->item_count , nit);\r
+               }\r
+       }\r
+\r
+       nit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index + 2);\r
+       if(nit != NULL){                \r
+               if(nit->on_show == EINA_FALSE){\r
+                       _gallery_add_image(obj, index + 2, nit);\r
+               }\r
+       }\r
+\r
+       nit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index + 3);\r
+       if(nit != NULL){                \r
+               if(nit->on_show == EINA_FALSE){\r
+                       _gallery_add_image(obj, index + 3, nit);\r
+               }\r
+       }       \r
+\r
+       if(index > wd->item_count *2){\r
+               Elm_Gallery_Item *pit = NULL;\r
+               pit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index - wd->item_count  -2);\r
+               if(pit != NULL){\r
+                       _gallery_del_image(pit);\r
+               }\r
+\r
+               pit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index - wd->item_count  -3);\r
+               if(pit != NULL){\r
+                       _gallery_del_image(pit);        \r
+               }\r
+\r
+               pit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index - wd->item_count  -4);\r
+               if(pit != NULL){\r
+                       _gallery_del_image(pit);        \r
+               }               \r
+       }\r
+\r
+}\r
+\r
+static void _gallery_move_left_cb(Evas_Object *obj, int index)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       Elm_Gallery_Item *nit = NULL;\r
+\r
+       nit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index - wd->item_count );\r
+       if(nit != NULL){\r
+               if(nit->on_show == EINA_FALSE){\r
+                       _gallery_add_image(obj, index - wd->item_count , nit);\r
+               }\r
+       }\r
+\r
+       nit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index - 2);\r
+       if(nit != NULL){\r
+               if(nit->on_show == EINA_FALSE){\r
+                       _gallery_add_image(obj, index - 2, nit);\r
+               }\r
+       }\r
+\r
+       nit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index - 3);\r
+       if(nit != NULL){\r
+               if(nit->on_show == EINA_FALSE){\r
+                       _gallery_add_image(obj, index - 3, nit);\r
+               }\r
+       }\r
+       \r
+       if(index + wd->item_count + 4 < eina_list_count(wd->list)){\r
+               Elm_Gallery_Item *pit = NULL;\r
+               pit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index + wd->item_count  +2);\r
+               if(pit != NULL){\r
+                       _gallery_del_image(pit);\r
+               }\r
+\r
+               pit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index + wd->item_count  +3);\r
+               if(pit != NULL){\r
+                       _gallery_del_image(pit);\r
+               }\r
+\r
+               pit = (Elm_Gallery_Item *)eina_list_nth(wd->list, index + wd->item_count  +4);\r
+               if(pit != NULL){\r
+                       _gallery_del_image(pit);\r
+               }               \r
+       }\r
+}\r
+\r
+\r
+/**\r
+  * This function  makes a new gallery object\r
+  * @param parent The parent object\r
+  * @return  new gallery object \r
+  *\r
+  * @ingroup Gallery\r
+  */\r
+EAPI Evas_Object *elm_gallery_add(Evas_Object *parent)\r
+{\r
+       Evas_Object *obj;\r
+       Widget_Data *wd;\r
+       if (!parent) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       }\r
+\r
+       if ((obj = gallery_new(parent))) {\r
+               if (!(wd = evas_object_smart_data_get(obj))) {\r
+                       evas_object_del(obj);\r
+                       return NULL;\r
+               }\r
+       }\r
+       \r
+       elm_widget_sub_object_add (parent, obj);\r
+       \r
+       return obj;\r
+}\r
+\r
+\r
+/**\r
+  * The function appends an item and return the item class.\r
+  * @param obj The gallery object\r
+  * @param photo_file image file name\r
+  * @return new Elm_Gallery_Item\r
+  *\r
+  * @ingroup Gallery\r
+  */\r
+EAPI Elm_Gallery_Item *elm_gallery_item_append(Evas_Object *obj, const char *photo_file)\r
+{\r
+       Widget_Data *wd;\r
+       Elm_Gallery_Item *it;\r
+       if (!obj || !(wd = evas_object_smart_data_get(obj))) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       }\r
+       \r
+       it = (Elm_Gallery_Item *)calloc(1, sizeof(Elm_Gallery_Item));\r
+       it->path = eina_stringshare_add(photo_file);\r
+       it->parent = obj;\r
+       it->obj = NULL;         \r
+       it->on_show = EINA_FALSE;\r
+                       \r
+       wd->list = eina_list_append(wd->list, it);\r
+\r
+       _resize_gallery(obj);\r
+\r
+       return it;\r
+}\r
+\r
+\r
+/**\r
+  * The function prepends an item and return the item class.\r
+  * @param obj The gallery object\r
+  * @param photo_file image file name\r
+  * @return new Elm_Gallery_Item\r
+  *\r
+  * @ingroup Gallery\r
+  */\r
+EAPI Elm_Gallery_Item *elm_gallery_item_prepend(Evas_Object *obj, const char *photo_file)\r
+{\r
+       Widget_Data *wd;\r
+       Elm_Gallery_Item *it;\r
+       if (!obj || !(wd = evas_object_smart_data_get(obj))) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       }\r
+\r
+       it = (Elm_Gallery_Item *)calloc(1, sizeof(Elm_Gallery_Item));\r
+       it->path = eina_stringshare_add(photo_file);\r
+       it->parent = obj;\r
+       it->obj = NULL;         \r
+       it->on_show = EINA_FALSE;\r
+       \r
+       wd->list = eina_list_prepend(wd->list, it);\r
+       \r
+       _resize_gallery(obj);\r
+       \r
+       return it;\r
+}\r
+\r
+\r
+/**\r
+  * The function deletes the item\r
+  * @param it Elm_Gallery_Item\r
+  *\r
+  * @ingroup Gallery\r
+  */\r
+EAPI void elm_gallery_item_del(Elm_Gallery_Item *it)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       if (!it || !(wd = evas_object_smart_data_get(it->parent))) {\r
+               errno = EINVAL;\r
+               return;\r
+       }\r
+\r
+       wd->list = eina_list_remove(wd->list, it);\r
+\r
+       _resize_gallery(wd->obj);\r
+}\r
+\r
+\r
+/**\r
+  * The function gets the file name of certain item using it's item class\r
+  * @param it Elm_Gallery_Item\r
+  * @return (char*) file name path\r
+  *\r
+  * @ingroup Gallery\r
+  */\r
+EAPI const char *elm_gallery_item_file_get(Elm_Gallery_Item *it)\r
+{\r
+       if (!it) {\r
+               errno = EINVAL;\r
+               return NULL;\r
+       }\r
+       \r
+       return it->path;\r
+}\r
+\r
+\r
+EAPI void elm_gallery_item_show(Elm_Gallery_Item *it)\r
+{\r
+       Widget_Data *wd;\r
+       Elm_Gallery_Item *_it;\r
+       Eina_List *l;\r
+       int index = 0;\r
+       \r
+       if (!it || !it->parent|| (!(wd = evas_object_smart_data_get(it->parent)))) {\r
+               errno = EINVAL;\r
+               return;\r
+       }       \r
+   \r
+       EINA_LIST_FOREACH(wd->list, l, _it) \r
+       {\r
+               if (_it == it) {\r
+                       break;\r
+               }\r
+               index++;\r
+       }\r
+       \r
+       wd->init_num = index;\r
+\r
+       _update_gallery(it->parent);\r
+\r
+       if(wd->eidler){\r
+               ecore_idler_del(wd->eidler);\r
+               wd->eidler = NULL;\r
+       }\r
+       \r
+       wd->eidler = ecore_idler_add(_gallery_idle_handler_cb, wd);     \r
+}\r
+\r
+\r
+/**\r
+  * The function gets the list of item class\r
+  * @param obj The gallery object\r
+  * @return new Eina_List of All item\r
+  *\r
+  * @ingroup Gallery\r
+  */\r
+EAPI Eina_List *elm_gallery_item_list_get(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return NULL;\r
+       \r
+       return wd->list;\r
+}\r
+\r
+\r
+\r
+/**\r
+  * The function set the type value \r
+  * @param parent The parent object\r
+  * @param type Type 1 : image swticher type Type 2 : gallery type\r
+  *\r
+  * @ingroup Gallery\r
+  */\r
+EAPI void elm_gallery_set_type(Evas_Object *obj,int type)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       wd->item_type = type;\r
+       \r
+       _gallery_set_all_status(obj,type);\r
+}\r
+\r
+\r
+\r
+/**\r
+  *The function determines a max number of images to be shown in a row\r
+  * @param parent The parent object\r
+  * @param max_value the value of max\r
+  *\r
+  * @ingroup Gallery\r
+  */  \r
+EAPI void elm_gallery_set_max_count(Evas_Object *obj,int max_value)\r
+{\r
+       Widget_Data *wd;\r
+       wd = evas_object_smart_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       wd->item_count = max_value;\r
+}\r
+\r
+\r
diff --git a/src/lib/elm_gridbox.c b/src/lib/elm_gridbox.c
new file mode 100644 (file)
index 0000000..cbd7db4
--- /dev/null
@@ -0,0 +1,355 @@
+#include <Elementary.h>
+
+#include "elm_priv.h"
+
+/**
+ * @defgroup Gridbox Gridbox
+ * @ingroup Elementary
+ *
+ * This is a gridbox widget to show multiple objects in a grid
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *tbl, *scr;
+   Evas_Coord itemsize_h, itemsize_v;
+   Evas_Coord minw, minh;
+   Evas_Coord horizontal, vertical;
+   int x, y;
+   Eina_Bool homogeneous:1;
+};
+
+static void _del_hook(Evas_Object *obj);
+
+static void _sizing_eval(Evas_Object *obj, int mode);
+
+static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _changed_size_min(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _sub_del(void *data, Evas_Object *obj, void *event_info);
+
+static void _show_event(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static void
+_del_pre_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   evas_object_event_callback_del_full(wd->tbl, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+   evas_object_event_callback_del_full(wd->tbl, EVAS_CALLBACK_RESIZE, _changed_size_min, obj);
+   evas_object_del(wd->tbl);
+   wd->tbl = NULL;
+   evas_object_del(wd->scr);
+   wd->scr = NULL;
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   free(wd);
+}
+
+static Eina_Bool
+_arrange_table(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   Eina_List *l, *l_temp = NULL;
+
+   Evas_Object *item;
+
+   int i = 0;
+
+   if (wd)
+     {
+        if (wd->tbl)
+          {
+             int index = eina_list_count(evas_object_table_children_get(wd->tbl));
+             if (!index) return EINA_FALSE;
+
+             elm_gridbox_item_size_set(obj, wd->itemsize_h, wd->itemsize_v);
+             l = evas_object_table_children_get(wd->tbl);
+
+             EINA_LIST_FOREACH(l, l_temp, item)
+               {
+                  evas_object_table_unpack(wd->tbl, item);
+                  elm_widget_sub_object_del(wd->tbl, item);
+                  evas_object_table_pack(wd->tbl, item, i % wd->x, i / wd->x, 1, 1);
+                  i++;
+               }
+          }
+     }
+   return EINA_TRUE;
+}
+
+static void
+_sizing_eval(Evas_Object *obj, int mode)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+
+   Evas_Coord w, h;
+
+   evas_object_size_hint_min_get(wd->scr, &minw, &minh);
+   evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+   evas_object_geometry_get(wd->scr, NULL, NULL, &w, &h);
+
+   if (w < minw) w = minw;
+   if (h < minh) h = minh;
+   if ((maxw >= 0) && (w > maxw)) 
+     w = maxw;
+   if ((maxh >= 0) && (h > maxh))
+     h = maxh;
+   evas_object_resize(obj, w, h);
+
+   wd->minw = w;
+   wd->minh = h;
+   if (w < wd->itemsize_h || h < wd->itemsize_v)
+     return;
+   if (wd->homogeneous)
+     {
+        wd->x = w / wd->itemsize_h;
+        wd->y = h / wd->itemsize_v;
+        wd->horizontal = (wd->minw - wd->x * wd->itemsize_h) / wd->x;
+        wd->vertical = (wd->minh - wd->y * wd->itemsize_v) / wd->y;
+        elm_gridbox_padding_set(obj, wd->horizontal, wd->vertical);
+     }
+
+   if (!mode)
+     _arrange_table(obj);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _sizing_eval(data, 0);
+}
+
+static void
+_changed_size_min(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _sizing_eval(data, 0);
+}
+
+static void
+_sub_del(void *data, Evas_Object *obj, void *event_info)
+{
+   _sizing_eval(obj, 1);
+}
+
+static void
+_show_event(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _sizing_eval(data, 0);
+}
+
+static void
+_freeze_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   evas_object_smart_callback_call(wd->scr, "scroll-freeze-on", NULL);
+}
+
+static void
+_freeze_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   evas_object_smart_callback_call(wd->scr, "scroll-freeze-off", NULL);
+}
+
+/**
+ * Add a new gridbox to the parent
+ *
+ * @param[in] parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Gridbox
+ */
+EAPI Evas_Object *
+elm_gridbox_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+
+   Evas *e;
+
+   Widget_Data *wd;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   obj = elm_widget_add(e);
+   elm_widget_type_set(obj, "gridbox");
+   elm_widget_sub_object_add(parent, obj);
+   elm_widget_data_set(obj, wd);
+   elm_widget_del_hook_set(obj, _del_hook);
+   elm_widget_del_pre_hook_set(obj, _del_pre_hook);
+
+   wd->scr = elm_scroller_add(parent);
+   elm_widget_resize_object_set(obj, wd->scr);
+   elm_scroller_bounce_set(wd->scr, 0, 1);
+
+   wd->tbl = evas_object_table_add(e);
+   evas_object_size_hint_weight_set(wd->tbl, 0.0, 0.0);
+   elm_scroller_content_set(wd->scr, wd->tbl);
+   evas_object_show(wd->tbl);
+
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _changed_size_min, obj);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_SHOW, _show_event, obj);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
+
+   _sizing_eval(obj, 0);
+
+   return obj;
+}
+
+/**
+ * Set padding between cells.
+ *
+ * @param[in] obj The layout object.
+ * @param[in] horizontal set the horizontal padding.
+ * @param[in] vertical set the vertical padding.
+ *
+ * @ingroup Gridbox
+ */
+EAPI void
+elm_gridbox_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+
+   wd->horizontal = horizontal;
+   wd->vertical = vertical;
+   if (wd->tbl)
+     evas_object_table_padding_set(wd->tbl, horizontal, vertical);
+}
+
+/**
+ * Set gridbox item size
+ *
+ * @param[in] obj The gridbox object
+ * @param[in] h_pagesize The horizontal item size
+ * @param[in] v_pagesize The vertical item size
+ *
+ * @ingroup Gridbox
+ */
+EAPI void
+elm_gridbox_item_size_set(Evas_Object *obj, Evas_Coord h_itemsize, Evas_Coord v_itemsize)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   Evas_Coord minw = -1, minh = -1;
+
+   Evas_Coord w, h;
+
+   if (!wd) return;
+
+   wd->itemsize_h = h_itemsize;
+   wd->itemsize_v = v_itemsize;
+   evas_object_size_hint_min_get(wd->scr, &minw, &minh);
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   if (w < minw)
+     w = minw;
+   if (h < minh)
+     h = minh;
+   wd->x = w / h_itemsize;
+   wd->y = h / v_itemsize;
+
+   if (!wd->x)
+     wd->x = 1;
+   if (!wd->y)
+     wd->y = 1;
+   _sizing_eval(obj, 1);
+}
+
+/**
+ * Add a subobject on the gridbox
+ *
+ * @param[in] obj The table object
+ * @param[in] subobj The subobject to be added to the gridbox
+ *
+ * @ingroup Gridbox
+ */
+EAPI void
+elm_gridbox_pack(Evas_Object *obj, Evas_Object *subobj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   int index = eina_list_count(evas_object_table_children_get(wd->tbl));
+
+   evas_object_size_hint_min_set(subobj, wd->itemsize_h, wd->itemsize_v);
+   evas_object_size_hint_max_set(subobj, wd->itemsize_h, wd->itemsize_v);
+   elm_widget_sub_object_add(obj, subobj);
+   evas_object_table_pack(wd->tbl, subobj, index % wd->x, index / wd->x, 1, 1);
+}
+
+/**
+ * Unpack a subobject on the gridbox
+ *
+ * @param[in] obj The gridbox object
+ * @param[in] subobj The subobject to be removed to the gridbox
+ *
+ * @ingroup Gridbox
+ */
+EAPI Eina_Bool
+elm_gridbox_unpack(Evas_Object *obj, Evas_Object *subobj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   Eina_Bool ret = 0;
+
+   elm_widget_sub_object_del(wd->tbl, subobj);
+   ret = evas_object_table_unpack(wd->tbl, subobj);
+
+   _arrange_table(obj);
+
+   return ret;
+}
+
+/**
+ * Get the list of children for the gridbox.
+ *
+ * @param[in] obj The gridbox object
+ *
+ * @ingroup Gridbox
+ */
+EAPI Eina_List *
+elm_gridbox_children_get(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   Eina_List *new_list = NULL;
+
+   new_list = evas_object_table_children_get(wd->tbl);
+
+   return new_list;
+}
+
+/**
+ * Set homogenous paddding layout
+ *
+ * @param[in] obj The gridbox object
+ * @param[in] homogenous The homogenous flag (1 = on, 0 = off)
+ *
+ * @ingroup Gridbox
+ */
+EAPI void
+elm_gridbox_homogenous_padding_set(Evas_Object *obj, Eina_Bool homogenous)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   wd->homogeneous = homogenous;
+}
diff --git a/src/lib/elm_hor_scroller.c b/src/lib/elm_hor_scroller.c
new file mode 100644 (file)
index 0000000..a502204
--- /dev/null
@@ -0,0 +1,572 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+#include "els_scroller.h"
+
+/**
+ * @defgroup Scroller Scroller
+ * @ingroup Elementary
+ *
+ * A scroller holds a single object and "scrolls it around". This means that
+ * it allows the user to use a scrollbar (or a finger) to drag the viewable
+ * region around, allowing to move through a much larger object that is
+ * contained in the scroller. The scroiller will always have a small minimum
+ * size by default as it won't be limited by the contents of the scroller.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * edge,left - the left edge of the content has been reached
+ *
+ * edge,right - the right edge of the content has been reached
+ *
+ * edge,top - the top edge of the content has been reached
+ *
+ * edge,bottom - the bottom edge of the content has been reached
+ *
+ * scroll - the content has been scrolled (moved)
+ *
+ * scroll,anim,start - scrolling animation has started
+ *
+ * scroll,anim,stop - scrolling animation has stopped
+ *
+ * scroll,drag,start - dragging the contents around has started
+ *
+ * scroll,drag,stop - dragging the contents around has stopped
+ */
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *scr;
+   Evas_Object *content;
+   const char *widget_name, *widget_base;
+   Eina_Bool min_w : 1;
+   Eina_Bool min_h : 1;
+   double pagerel_h, pagerel_v;
+   Evas_Coord pagesize_h, pagesize_v;
+};
+
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _show_region_hook(void *data, Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _sub_del(void *data, Evas_Object *obj, void *event_info);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->scr)
+   {
+//       elm_smart_scroller_theme_set(wd->scr, "scroller", "base", elm_widget_style_get(obj));
+         hor_elm_smart_scroller_theme_set(obj, wd->scr,
+                                               wd->widget_name,
+                                               wd->widget_base,
+                                               elm_widget_style_get(obj));
+//       edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
+   }
+   _sizing_eval(obj);
+}
+
+static void
+_show_region_hook(void *data, Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   Evas_Coord x, y, w, h;
+   if (!wd) return;
+   elm_widget_show_region_get(obj, &x, &y, &w, &h);
+   hor_elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord  vw, vh, minw, minh, maxw, maxh, w, h, vmw, vmh;
+   double xw, xy;
+
+   if (!wd) return;
+   evas_object_size_hint_min_get(wd->content, &minw, &minh);
+   evas_object_size_hint_max_get(wd->content, &maxw, &maxh);
+   evas_object_size_hint_weight_get(wd->content, &xw, &xy);
+   hor_elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
+   if (xw > 0.0)
+     {
+       if ((minw > 0) && (vw < minw)) vw = minw;
+       else if ((maxw > 0) && (vw > maxw)) vw = maxw;
+     }
+   else if (minw > 0) vw = minw;
+   if (xy > 0.0)
+     {
+       if ((minh > 0) && (vh < minh)) vh = minh;
+       else if ((maxh > 0) && (vh > maxh)) vh = maxh;
+     }
+   else if (minh > 0) vh = minh;
+   evas_object_resize(wd->content, vw, vh);
+   w = -1;
+   h = -1;
+   edje_object_size_min_calc(hor_elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
+   if (wd->min_w) w = vmw + minw;
+   if (wd->min_h) h = vmh + minh;
+   evas_object_size_hint_min_set(obj, w, h);
+}
+
+static void
+_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _sizing_eval(data);
+}
+
+static void
+_sub_del(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *sub = event_info;
+
+   if (!wd) return;
+   if (sub == wd->content)
+     {
+       elm_widget_on_show_region_hook_set(wd->content, NULL, NULL);
+       evas_object_event_callback_del_full (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+           _changed_size_hints, obj);
+       wd->content = NULL;
+       _sizing_eval(obj);
+     }
+}
+
+static void
+_hold_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   hor_elm_smart_scroller_hold_set(wd->scr, 1);
+}
+
+static void
+_hold_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   hor_elm_smart_scroller_hold_set(wd->scr, 0);
+}
+
+static void
+_freeze_on(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   hor_elm_smart_scroller_freeze_set(wd->scr, 1);
+}
+
+static void
+_freeze_off(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   hor_elm_smart_scroller_freeze_set(wd->scr, 0);
+}
+
+static void
+_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _sizing_eval(data);
+}
+
+static void
+_edge_left(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge,left", NULL);
+}
+
+static void
+_edge_right(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge,right", NULL);
+}
+
+static void
+_edge_top(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge,top", NULL);
+}
+
+static void
+_edge_bottom(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "edge,bottom", NULL);
+}
+
+static void
+_scroll(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "scroll", NULL);
+}
+
+static void
+_scroll_anim_start(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "scroll,anim,start", NULL);
+}
+
+static void
+_scroll_anim_stop(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "scroll,anim,stop", NULL);
+}
+
+static void
+_scroll_drag_start(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "scroll,drag,start", NULL);
+}
+
+static void
+_scroll_drag_stop(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_smart_callback_call(data, "scroll,drag,stop", NULL);
+}
+
+/**
+ * Add a new scroller to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Scroller
+ */
+EAPI Evas_Object *
+hor_elm_scroller_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+   Evas_Coord minw, minh;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   obj = elm_widget_add(e);
+   elm_widget_type_set(obj, "scroller");
+   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);
+   wd->widget_name = eina_stringshare_add("scroller");
+   wd->widget_base = eina_stringshare_add("base");
+
+   wd->scr = hor_elm_smart_scroller_add(e);
+   elm_widget_resize_object_set(obj, wd->scr);
+   evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                 _changed_size_hints, obj);
+
+   edje_object_size_min_calc(hor_elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
+
+   evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
+   evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
+   evas_object_smart_callback_add(wd->scr, "scroll", _scroll, obj);
+   evas_object_smart_callback_add(wd->scr, "animate,start", _scroll_anim_start, obj);
+   evas_object_smart_callback_add(wd->scr, "animate,stop", _scroll_anim_stop, obj);
+   evas_object_smart_callback_add(wd->scr, "drag,start", _scroll_drag_start, obj);
+   evas_object_smart_callback_add(wd->scr, "drag,stop", _scroll_drag_stop, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the content object
+ *
+ * XXX
+ *
+ * @param obj The scroller object
+ * @param content The new content object
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_content_set(Evas_Object *obj, Evas_Object *content)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((wd->content != content) && (wd->content))
+     elm_widget_sub_object_del(obj, wd->content);
+   wd->content = content;
+   if (content)
+     {
+       elm_widget_on_show_region_hook_set(content, _show_region_hook, obj);
+       elm_widget_sub_object_add(obj, content);
+       hor_elm_smart_scroller_child_set(wd->scr, content);
+       evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       _sizing_eval(obj);
+     }
+}
+
+/**
+ * Set custom theme elements for the scroller
+ *
+ * @param obj The scroller object
+ * @param widget The widget name to use (default is "scroller")
+ * @param base The base name to use (default is "base")
+ */
+EAPI void
+hor_elm_scroller_custom_widget_base_theme_set(Evas_Object *obj, const char *widget, const char *base)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       if ((!widget) || (!base)) return;
+       if (eina_stringshare_replace(&wd->widget_name, widget) |
+           eina_stringshare_replace(&wd->widget_base, base))
+               _theme_hook(obj);
+}
+
+/**
+ * Make the scroller minimum size limited to the minimum size of the content
+ *
+ * By default the scroller will be as small as its design allows, irrespective
+ * of its content. This will make the scroller minimum size the right size
+ * horizontally and/or vertically to perfectly fit its content.
+ *
+ * @param obj The scroller object
+ * @param w Enable limiting minimum size horizontally
+ * @param h Enable limiting minimum size vertically
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->min_w = w;
+   wd->min_h = h;
+   _sizing_eval(obj);
+}
+
+/**
+ * Show a specific virtual region within the scroller content object
+ *
+ * This will ensure all (or part if it does not fit) of the designated
+ * region in the virtual content object (0, 0 starting at the top-left of the
+ * virtual content object) is shown within the scroller.
+ *
+ * @param obj The scroller object
+ * @param x X coordinate of the region
+ * @param y Y coordinate of the region
+ * @param w Width of the region
+ * @param h Height of the region
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   hor_elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
+}
+
+/**
+ * Set the scroller scrollbar policy
+ *
+ * This sets the scrollbar visibility policy for the given scroller.
+ * ELM_SMART_SCROLLER_POLICY_AUTO means the scrollber is made visible if it
+ * is needed, and otherwise kept hidden. ELM_SMART_SCROLLER_POLICY_ON turns
+ * it on all the time, and ELM_SMART_SCROLLER_POLICY_OFF always keeps it off.
+ * This applies respectively for the horizontal and vertical scrollbars.
+ *
+ * @param obj The scroller object
+ * @param policy_h Horizontal scrollbar policy
+ * @param policy_v Vertical scrollbar policy
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   const Elm_Scroller_Policy map[3] =
+     {
+       ELM_SMART_SCROLLER_POLICY_AUTO,
+         ELM_SMART_SCROLLER_POLICY_ON,
+         ELM_SMART_SCROLLER_POLICY_OFF
+     };
+   if (!wd) return;
+   if ((policy_h < 0) || (policy_h >= 3) || (policy_v < 0) || (policy_v >= 3))
+     return;
+   hor_elm_smart_scroller_policy_set(wd->scr, map[policy_h], map[policy_v]);
+}
+
+/**
+ * Get the currently visible content region
+ *
+ * This gets the current region in the content object that is visible through
+ * the scroller. Also see elm_scroller_region_show(). The region co-ordinates
+ * are returned in the @p x, @p y, @p w, @p h values pointed to.
+ *
+ * @param obj The scroller object
+ * @param x X coordinate of the region
+ * @param y Y coordinate of the region
+ * @param w Width of the region
+ * @param h Height of the region
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_region_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if ((x) && (y)) hor_elm_smart_scroller_child_pos_get(wd->scr, x, y);
+   if ((w) && (h)) hor_elm_smart_scroller_child_viewport_size_get(wd->scr, w, h);
+}
+
+/**
+ * Get the size of the content child object
+ *
+ * This gets the size of the child object of the scroller. Actually the
+ * content of a scroller doesn't specifically need to be an actual object
+ * as it can be virtual and defined purely by callbacks.
+ *
+ * @param obj The scroller object
+ * @param w Width return
+ * @param h Height return
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   evas_object_geometry_get(wd->content, NULL, NULL, w, h);
+}
+
+/**
+ * Set bouncing behavior
+ *
+ * When scrolling, the scroller may "bounce" when reaching an edge of the child
+ * object. This is a visual way to indicate the end has been reached. This is
+ * enabled by default for both axes. This will set if it is enabled for that
+ * axis with the boolean parameers for each axis.
+ *
+ * @param obj The scroller object
+ * @param h_bounce Will the scroller bounce horizontally or not
+ y Y coordinate of the region
+ w Width of the region
+ h Height of the region
+
+ EAPI void elm_scroller_region_show ( Evas_Object *  obj, * @param v_bounce Will the scroller bounce vertically or not
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   hor_elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
+}
+
+/**
+ * Set scroll page size relative to viewport size
+ *
+ * The scroller is sapale of limiting scrolling by the user to "pages". That
+ * is to jump by and only show a "whole page" at a time as if the continuous
+ * area of the scroller conent is split into page sized pieces. This sets
+ * the size of a page relative to the viewport of the scroller. 1.0 is "1
+ * viewport" is size (horizontally or vertically). 0.0 turns it off in that
+ * axis. This is mutually exclusive with page size
+ * (see elm_scroller_page_size_set()  for more information). likewise 0.5
+ * is "half a viewport". Sane usable valus are normally between 0.0 and 1.0
+ * including 1.0. If you only want 1 axis to be page "limited", use 0.0 for
+ * the other axis.
+ *
+ * @param obj The scroller object
+ * @param h_pagerel The horizontal page relative size
+ * @param v_pagerel The vertical page relative size
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->pagerel_h = h_pagerel;
+   wd->pagerel_v = v_pagerel;
+   hor_elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v,
+                                 wd->pagesize_h, wd->pagesize_v);
+}
+
+/**
+ * Set scroll page size
+ *
+ * See also elm_scroller_page_relative_set(). This, instead of a page size
+ * being relaive to the viewport, sets it to an absolute fixed value, with
+ * 0 turning it off for that axis.
+ *
+ * @param obj The scroller object
+ * @param h_pagesize The horizontal page size
+ * @param v_pagesize The vertical page size
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->pagesize_h = h_pagesize;
+   wd->pagesize_v = v_pagesize;
+   hor_elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v,
+                                 wd->pagesize_h, wd->pagesize_v);
+}
+
+/**
+ * Show a specific virtual region within the scroller content object
+ *
+ * This will ensure all (or part if it does not fit) of the designated
+ * region in the virtual content object (0, 0 starting at the top-left of the
+ * virtual content object) is shown within the scroller. Unlike
+ * elm_scroller_region_show(), this allow the scroller to "smoothly slide"
+ * to this location (if configuration in general calls for transitions). It
+ * may not jump immediately to the new location and make take a while and
+ * show other content along the way.
+ *
+ * @param obj The scroller object
+ * @param x X coordinate of the region
+ * @param y Y coordinate of the region
+ * @param w Width of the region
+ * @param h Height of the region
+ *
+ * @ingroup Scroller
+ */
+EAPI void
+hor_elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   hor_elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
+}
diff --git a/src/lib/elm_ratingbar.c b/src/lib/elm_ratingbar.c
new file mode 100644 (file)
index 0000000..0013687
--- /dev/null
@@ -0,0 +1,278 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Ratingbar Ratingbar
+ * @ingroup Elementary
+ *
+ * This is a ratingbar.
+ */
+
+
+#define RATING_MAX 5                   
+
+typedef struct _Widget_Data Widget_Data;
+struct _Widget_Data {
+       Evas_Object *base;
+       Evas_Coord x, y, w, h;
+       int rating;
+       bool pressed;
+};
+
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _update_ratingbar(Evas_Object *obj);
+
+
+static void
+_del_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       
+       _elm_theme_object_set(obj, wd->base, "ratingbar", "base", elm_widget_style_get(obj));
+       _update_ratingbar(obj);
+       _sizing_eval(obj);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+       if (!wd) return;
+       
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       evas_object_size_hint_min_set(obj, minw, minh);
+       evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_changed(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       evas_object_smart_callback_call(obj, "changed", NULL);
+}
+
+static void
+_update_ratingbar(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       char partname[20] = {0,};
+       int i;
+       if (!wd) return;        
+
+       for(i=1; i<=RATING_MAX; i++)
+       {
+               sprintf(partname, "elm.star.%d", i);
+
+               if(wd->pressed == FALSE){
+                       if(i <= wd->rating)     edje_object_signal_emit(wd->base, "elm,star,selected", partname);               
+                       else    edje_object_signal_emit(wd->base, "elm,star,unselected", partname);
+               }else{
+                       if(i <= wd->rating)     edje_object_signal_emit(wd->base, "elm,star,pressed,on", partname);             
+                       else    edje_object_signal_emit(wd->base, "elm,star,pressed,off", partname);
+               }
+       }
+               
+       _sizing_eval(obj);
+}
+
+static int
+_determine_rating(Evas_Coord x, Evas_Coord w, Evas_Coord ev_x)
+{
+       int rating = 0;
+       
+       if(ev_x < x){
+               rating = 0;
+       }else if(ev_x < x + 0.2*w){
+               rating = 1;
+       }else if(ev_x < x + 0.4*w){
+               rating = 2;
+       }else if(ev_x < x + 0.6*w){
+               rating = 3;
+       }else if(ev_x < x + 0.8*w){
+               rating = 4;
+       }else if(ev_x < x + w){
+               rating = 5;
+       }else{
+               rating = 5;
+       }
+
+       return rating;
+}
+
+static void 
+_resize_cb(void *data, Evas *evas, Evas_Object *obj, void *event)
+{
+       Widget_Data *wd = elm_widget_data_get(data);    
+       if (!wd) return;
+
+       evas_object_geometry_get(obj, NULL, NULL, &wd->w, &wd->h);
+}
+
+static void 
+_move_cb(void *data, Evas *evas, Evas_Object *obj, void *event)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+       if (!wd) return;
+
+       evas_object_geometry_get(obj, &wd->x, &wd->y, NULL, NULL);
+}
+
+static void
+_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Event_Mouse_Down *ev = event_info;
+       if (!wd) return;        
+       int rating_old = wd->rating;
+
+       wd->pressed = TRUE;
+       wd->rating = _determine_rating(wd->x, wd->w, ev->canvas.x);
+       _update_ratingbar(data);        
+       
+       if(wd->rating != rating_old)    
+               _changed(data);
+}
+
+static void
+_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Event_Mouse_Move *ev = event_info;
+       if (!wd || !ev->buttons) return;
+       int rating_old = wd->rating;
+
+       wd->pressed = TRUE;
+       wd->rating = _determine_rating(wd->x, wd->w, ev->cur.canvas.x);
+       _update_ratingbar(data);
+       
+       if(wd->rating != rating_old)    
+               _changed(data);
+}
+
+static void
+_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Event_Mouse_Up *ev = event_info;
+       if (!wd) return;
+       int rating_old = wd->rating;
+
+       wd->pressed = FALSE;
+       wd->rating  = _determine_rating(wd->x, wd->w, ev->canvas.x);
+       _update_ratingbar(data);
+
+       if(wd->rating != rating_old)    
+               _changed(data);
+}
+
+static void
+_event_init(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if(!wd || !wd->base)    return;
+
+       evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
+       evas_object_event_callback_add(wd->base, EVAS_CALLBACK_MOVE, _move_cb, obj);
+       evas_object_event_callback_add(wd->base, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, obj);
+       evas_object_event_callback_add(wd->base, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, obj);
+       evas_object_event_callback_add(wd->base, EVAS_CALLBACK_MOUSE_UP, _mouse_up, obj);
+}
+
+/**
+ * Add a new ratingbar to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Ratingbar
+ */
+EAPI Evas_Object *
+elm_ratingbar_add(Evas_Object *parent)
+{
+       Evas_Object *obj;
+       Evas *e;
+       Widget_Data *wd;
+
+       wd = ELM_NEW(Widget_Data);
+       e = evas_object_evas_get(parent);
+       obj = elm_widget_add(e);
+       elm_widget_type_set(obj, "ratingbar");
+       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);
+       
+       wd->base = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->base, "ratingbar", "base", "default");
+       elm_widget_resize_object_set(obj, wd->base);
+       evas_object_show(wd->base);
+
+       wd->rating = 0;
+       wd->pressed = FALSE;
+       
+       _event_init(obj);
+       _update_ratingbar(obj);
+
+       return obj;
+}
+
+/**
+ * Set the current rating
+ *
+ * @param obj The ratingbar object
+ * @param rating The current rating 
+ *
+ * @ingroup Ratingbar
+ */
+EAPI void
+elm_ratingbar_rating_set(Evas_Object *obj, int rating)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       if(rating < 0 || rating > RATING_MAX){
+               fprintf(stderr, "Invalid the value of rating\n");
+               return;
+       }
+
+       if(wd->rating == rating) return;
+
+       wd->rating = rating;
+       _changed(obj);
+       _update_ratingbar(obj);
+}
+
+/**
+ * Get the current rating
+ *
+ * @param obj The ratingbar object 
+ * @return The current rating
+ *
+ * @ingroup Ratingbar
+ */
+EAPI int
+elm_ratingbar_rating_get(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return 0;
+
+       return wd->rating;
+}
+
+
diff --git a/src/lib/elm_scrolled_grid.c b/src/lib/elm_scrolled_grid.c
new file mode 100644 (file)
index 0000000..329956b
--- /dev/null
@@ -0,0 +1,1564 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Grid Scrolled Grid
+ * @ingroup Elementary
+ *
+ * This widget aims to position objects in a grid layout while actually
+ * building only the visible ones, using the same idea as genlist: the user
+ * define a class for each cell, specifying functions that will be called at
+ * object creation and deletion.
+ *
+ * Signals that you can add callbacks for are:
+ *
+ * clicked - The user has double-clicked a cell. The event_info parameter is
+ * the grid cell that was double-clicked.
+ *
+ * selected - The user has made an item selected. The event_info parameter is
+ * the grid cell that was selected.
+ *
+ * unselected - The user has made an item unselected. The event_info parameter
+ * is the grid cell that was unselected.
+ *
+ * realized - This is called when the cell in the grid is created as a real
+ * evas object. event_info is the grid cell that was created. The object may be
+ * deleted at any time, so it is up to the caller to not use the object pointer
+ * from elm_scrolled_grid_cell_object_get() in a way where it may point to
+ * freed objects.
+ *
+ * drag,start,up - Called when the cell in the grid has been dragged (not
+ * scrolled) up.
+ *
+ * drag,start,down - Called when the cell in the grid has been dragged (not
+ * scrolled) down.
+ *
+ * drag,start,left - Called when the cell in the grid has been dragged (not
+ * scrolled) left.
+ *
+ * drag,start,right - Called when the cell in the grid has been dragged (not
+ * scrolled) right.
+ *
+ * drag,stop - Called when the cell in the grid has stopped being dragged.
+ *
+ * drag - Called when the cell in the grid is being dragged.
+ *
+ * scroll - called when the content has been scrolled (moved).
+ *
+ * scroll,drag,start - called when dragging the content has started.
+ *
+ * scroll,drag,stop - called when dragging the content has stopped.
+ *
+ *
+ * A cell in the grid can have 0 or more text labels (they can be regular text
+ * or textblock - that's up to the style to determine), 0 or more icons (which
+ * are simply objects swallowed into the grid cell) and 0 or more boolean states
+ * that can be used for check, radio or other indicators by the edje theme style.
+ * A cell may be one of several styles (Elementary provides 1 by default -
+ * "default", but this can be extended by system or application custom
+ * themes/overlays/extensions).
+ *
+ * In order to implement the ability to add and delete cells on the fly, Grid
+ * implements a class/callback system where the application provides a structure
+ * with information about that type of cell (grid may contain multiple different
+ * cells with different classes, states and styles). Grid will call the functions
+ * in this struct (methods) when a cell is "realized" (that is created
+ * dynamically while scrolling). All objects will simply be deleted when no
+ * longer needed with evas_object_del(). The Elm_Genlist_Item_Class structure
+ * contains the following members:
+ *
+ * cell_style - This is a constant string and simply defines the name of the
+ * cell style. It must be specified and the default should be "default".
+ *
+ * func.label_get - This function is called when an actual cell object is
+ * created. The data parameter is the one passed to elm_scrolled_grid_cell_add()
+ * and related cell creation functions. The obj parameter is the grid object and
+ * the part parameter is the string name of the text part in the edje design that
+ * is listed as one of the possible labels that can be set. This function must
+ * return a strdup'()ed string as the caller will free() it when done.
+ *
+ * func.icon_get - This function is called when an actual item object is
+ * created. The data parameter is the one passed to elm_scrolled_grid_cell_add()
+ * and related cell creation functions. The obj parameter is the grid object and
+ * the part parameter is the string name of the icon part in the edje design that
+ * is listed as one of the possible icons that can be set. This must return NULL
+ * for no object or a valid object. The object will be deleted by grid on
+ * shutdown or when the cell is unrealized.
+ *
+ * func.state_get - This function is called when an actual cell object is
+ * created. The data parameter is the one passed to elm_scrolled_grid_cell_add()
+ * and related cell creation functions. The obj parameter is the grid object and
+ * the part parameter is the string name of th state part in the edje design that
+ * is listed as one of the possible states that can be set. Return 0 for false
+ * and 1 for true. Grid will emit a signal to the edje object with
+ * "elm,state,XXX,active" "elm" when true (the default is false), where XXX is
+ * the name of the part.
+ *
+ * func.del - This is called when elm_scrolled_grid_cell_del() is called on a
+ * cell or elm_scrolled_grid_clear() is called on the grid. This is intended for
+ * use when actual grid cells are deleted, so any backing data attached to the
+ * cell (e.g. its data parameter on creation) can be deleted.
+ *
+ * If the application wants multiple cells to be able to be selected,
+ * elm_scrolled_grid_multi_select_set() can enable this. If the grid is
+ * single-selection only (the default), then elm_scrolled_grid_select_cell_get()
+ * will return the selected cell, if any, or NULL if none is selected. If the
+ * grid is multi-select then elm_scrolled_grid_selected_cells_get() will return a
+ * list (that is only valid as long as no cells are modified (added, deleted,
+ * selected or unselected).
+ *
+ * If a cell changes (state of boolean changes, label or icons change), then use
+ * elm_scrolled_grid_cell_update() to have grid update the cell with the new
+ * state. Grid will re-realize the cell thus call the functions in the
+ * _Elm_Grid_Cell_Class for that cell.
+ *
+ * To programmatically (un)select a cell use elm_scrolled_grid_cell_selected_set().
+ * To get its selected state use elm_scrolled_grid_cell_selected_get(). To make a
+ * cell disabled (unable to be selected and appear differently) use
+ * elm_scrolled_grid_cell_disable_set() to set this and
+ * elm_scrolled_grid_cell_disable_get() to get the disabled state.
+ *
+ * Cells will only call their selection func and callback when first becoming
+ * selected. Any further clicks will do nothing, unless you enable always
+ * select with elm_scrolled_grid_always_select_mode_set(). This means event if
+ * selected, every click will make the selected callbacks be called.
+ * elm_scrolled_grid_no_select_mode_set() will turn off the ability to select
+ * items entirely and they will neither appear selected nor call selected
+ * callback function.
+ *
+ * Remember that you can create new styles and add your own theme augmentation
+ * per application with elm_theme_extension_add(). If you absolutely must have a
+ * specific style that overrides any theme the user or system sets up you can use
+ * elm_theme_overlay_add() to add such a file.
+ *
+ * --
+ * TODO:
+ *  * Handle non-homogeneous objects too.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+typedef struct _Pan Pan;
+
+#define PRELOAD 1
+
+struct _Elm_Grid_Cell
+{
+   Evas_Object *base, *spacer;
+   const Elm_Grid_Cell_Class *gcc;
+   Ecore_Timer *long_timer;
+   Widget_Data *wd;
+   Eina_List *labels, *icons, *states, *icon_objs;
+   const void *data;
+   struct
+     {
+       Evas_Smart_Cb func;
+       const void *data;
+     } func;
+
+   Evas_Coord x, y, dx, dy;
+   int relcount;
+
+   Eina_Bool want_unrealize : 1;
+   Eina_Bool realized : 1;
+   Eina_Bool dragging : 1;
+   Eina_Bool down : 1;
+   Eina_Bool delete_me : 1;
+   Eina_Bool display_only : 1;
+   Eina_Bool disabled : 1;
+   Eina_Bool selected : 1;
+   Eina_Bool hilighted : 1;
+   Eina_Bool walking : 1;
+};
+
+struct _Widget_Data
+{
+   Evas_Object *self, *scr;
+   Evas_Object *pan_smart;
+   Pan *pan;
+   Eina_List *cells;
+   Ecore_Job *calc_job;
+   Eina_List *selected;
+   double align_x, align_y;
+
+   Evas_Coord pan_x, pan_y;
+   Evas_Coord cell_width, cell_height; /* Each cell size */
+   Evas_Coord minw, minh;              /* Total obj size */
+   unsigned int nmax;
+
+   Eina_Bool horizontal : 1;
+   Eina_Bool on_hold : 1;
+   Eina_Bool longpressed : 1;
+   Eina_Bool multi : 1;
+   Eina_Bool no_select : 1;
+   Eina_Bool wasselected : 1;
+   Eina_Bool always_select : 1;
+};
+
+struct _Pan
+{
+   Evas_Object_Smart_Clipped_Data __clipped_data;
+   Widget_Data *wd;
+};
+
+static const char *widtype = NULL;
+static void _sizing_eval(Evas_Object *obj);
+static void _cell_hilight(Elm_Grid_Cell *cell);
+static void _cell_unrealize(Elm_Grid_Cell *cell);
+static void _cell_select(Elm_Grid_Cell *cell);
+static void _cell_unselect(Elm_Grid_Cell *cell);
+
+static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_object_theme_set(obj, wd->scr, "grid", "base",
+                                       elm_widget_style_get(obj));
+   _sizing_eval(obj);
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+   if (!wd) return;
+   evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   evas_object_del(wd->pan_smart);
+   wd->pan_smart = NULL;
+   elm_scrolled_grid_clear(obj);
+   free(wd);
+}
+
+static void
+_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Elm_Grid_Cell *cell = data;
+   Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
+
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+     {
+       if (!cell->wd->on_hold) {
+            cell->wd->on_hold = EINA_TRUE;
+            _cell_unselect(cell);
+       }
+     }
+   if ((cell->dragging) && (cell->down))
+     {
+       if (cell->long_timer)
+         {
+            ecore_timer_del(cell->long_timer);
+            cell->long_timer = NULL;
+         }
+       evas_object_smart_callback_call(cell->wd->self, "drag", cell);
+       return;
+     }
+   if ((!cell->down) || (cell->wd->longpressed))
+     {
+       if (cell->long_timer)
+         {
+            ecore_timer_del(cell->long_timer);
+            cell->long_timer = NULL;
+         }
+       return;
+     }
+   if (!cell->display_only)
+     elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   x = ev->cur.canvas.x - x;
+   y = ev->cur.canvas.y - y;
+   dx = x - cell->dx;
+   adx = dx;
+   if (adx < 0) adx = -dx;
+   dy = y - cell->dy;
+   ady = dy;
+   if (ady < 0) ady = -dy;
+   minw /= 2;
+   minh /= 2;
+   if ((adx > minw) || (ady > minh))
+     {
+       cell->dragging = 1;
+       if (cell->long_timer)
+         {
+            ecore_timer_del(cell->long_timer);
+            cell->long_timer = NULL;
+         }
+       if (cell->wd->wasselected)
+         _cell_unselect(cell);
+       cell->wd->wasselected = 0;
+       if (dy < 0)
+         {
+            if (ady > adx)
+              evas_object_smart_callback_call(cell->wd->self, "drag,start,up",
+                                              cell);
+            else
+              {
+                 if (dx < 0)
+                   evas_object_smart_callback_call(cell->wd->self,
+                                                   "drag,start,left", cell);
+              }
+         }
+       else
+         {
+            if (ady > adx)
+              evas_object_smart_callback_call(cell->wd->self,
+                                              "drag,start,down", cell);
+            else
+              {
+                 if (dx < 0)
+                   evas_object_smart_callback_call(cell->wd->self,
+                                                   "drag,start,left", cell);
+                 else
+                   evas_object_smart_callback_call(cell->wd->self,
+                                                   "drag,start,right", cell);
+              }
+         }
+     }
+}
+
+static int
+_long_press(void *data)
+{
+   Elm_Grid_Cell *cell = data;
+
+   cell->long_timer = NULL;
+   if ((cell->disabled) || (cell->dragging)) return 0;
+   cell->wd->longpressed = EINA_TRUE;
+   evas_object_smart_callback_call(cell->wd->self, "longpressed", cell);
+   return 0;
+}
+
+static void
+_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
+{
+   Elm_Grid_Cell *cell = data;
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord x, y;
+
+   if (ev->button != 1) return;
+   cell->down = 1;
+   cell->dragging = 0;
+   evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+   cell->dx = ev->canvas.x - x;
+   cell->dy = ev->canvas.y - y;
+   cell->wd->longpressed = EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) cell->wd->on_hold = EINA_TRUE;
+   else cell->wd->on_hold = EINA_FALSE;
+   cell->wd->wasselected = cell->selected;
+   _cell_hilight(cell);
+   if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
+     evas_object_smart_callback_call(cell->wd->self, "clicked", cell);
+   if (cell->long_timer) ecore_timer_del(cell->long_timer);
+   if (cell->realized)
+     cell->long_timer = ecore_timer_add(1.0, _long_press, cell);
+   else
+     cell->long_timer = NULL;
+}
+
+static void
+_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   Elm_Grid_Cell *cell = data;
+   Evas_Event_Mouse_Up *ev = event_info;
+   Eina_Bool dragged = EINA_FALSE;
+
+   if (ev->button != 1) return;
+   cell->down = EINA_FALSE;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) cell->wd->on_hold = EINA_TRUE;
+   else cell->wd->on_hold = EINA_FALSE;
+   if (cell->long_timer)
+     {
+       ecore_timer_del(cell->long_timer);
+       cell->long_timer = NULL;
+     }
+   if (cell->dragging)
+     {
+       cell->dragging = EINA_FALSE;
+       evas_object_smart_callback_call(cell->wd->self, "drag,stop", cell);
+       dragged = EINA_TRUE;
+     }
+   if (cell->wd->on_hold)
+     {
+       cell->wd->longpressed = EINA_FALSE;
+       cell->wd->on_hold = EINA_FALSE;
+       return;
+     }
+   if (cell->wd->longpressed)
+     {
+       cell->wd->longpressed = EINA_FALSE;
+       if (!cell->wd->wasselected)
+         _cell_unselect(cell);
+       cell->wd->wasselected = EINA_FALSE;
+       return;
+     }
+   if (dragged)
+     {
+       if (cell->want_unrealize)
+            _cell_unrealize(cell);
+     }
+   if ((cell->disabled) || dragged) return;
+   if (cell->wd->multi)
+     {
+       if (!cell->selected)
+         {
+            _cell_hilight(cell);
+            _cell_select(cell);
+         }
+       else _cell_unselect(cell);
+     }
+   else
+     {
+       if (!cell->selected)
+         {
+            while (cell->wd->selected) _cell_unselect(cell->wd->selected->data);
+         }
+       else
+         {
+            const Eina_List *l, *l_next;
+            Elm_Grid_Cell *cell2;
+
+            EINA_LIST_FOREACH_SAFE(cell->wd->selected, l, l_next, cell2)
+               if (cell2 != cell) _cell_unselect(cell2);
+         }
+       _cell_hilight(cell);
+       _cell_select(cell);
+     }
+}
+
+static void
+_cell_hilight(Elm_Grid_Cell *cell)
+{
+   if ((cell->wd->no_select) || (cell->delete_me) || (cell->hilighted)) return;
+   edje_object_signal_emit(cell->base, "elm,state,selected", "elm");
+   cell->hilighted = EINA_TRUE;
+}
+
+static void
+_cell_realize(Elm_Grid_Cell *cell)
+{
+   char buf[1024];
+
+   if ((cell->realized) || (cell->delete_me)) return;
+   cell->base = edje_object_add(evas_object_evas_get(cell->wd->self));
+   edje_object_scale_set(cell->base, elm_widget_scale_get(cell->wd->self) *
+                        _elm_config->scale);
+   evas_object_smart_member_add(cell->base, cell->wd->pan_smart);
+   elm_widget_sub_object_add(cell->wd->self, cell->base);
+   _elm_theme_object_set(cell->wd->self, cell->base, "grid", "cell/default",
+                         elm_widget_style_get(cell->wd->self));
+   cell->spacer = evas_object_rectangle_add(evas_object_evas_get(cell->wd->self));
+   evas_object_color_set(cell->spacer, 0, 0, 0, 0);
+   elm_widget_sub_object_add(cell->wd->self, cell->spacer);
+   evas_object_size_hint_min_set(cell->spacer, 2 * _elm_config->scale, 1);
+   edje_object_part_swallow(cell->base, "elm.swallow.pad", cell->spacer);
+
+   if (cell->gcc->func.label_get)
+     {
+       const Eina_List *l;
+       const char *key;
+
+       cell->labels = _elm_stringlist_get(edje_object_data_get(cell->base,
+                                                               "labels"));
+       EINA_LIST_FOREACH(cell->labels, l, key)
+         {
+            char *s = cell->gcc->func.label_get(cell->data, cell->wd->self,
+                                                l->data);
+            if (s)
+              {
+                 edje_object_part_text_set(cell->base, l->data, s);
+                 free(s);
+              }
+         }
+     }
+
+   if (cell->gcc->func.icon_get)
+     {
+       const Eina_List *l;
+       const char *key;
+
+       cell->icons = _elm_stringlist_get(edje_object_data_get(cell->base,
+                                                              "icons"));
+       EINA_LIST_FOREACH(cell->icons, l, key)
+         {
+            Evas_Object *ic = cell->gcc->func.icon_get(cell->data,
+                                                       cell->wd->self,
+                                                       l->data);
+            if (ic)
+              {
+                 cell->icon_objs = eina_list_append(cell->icon_objs, ic);
+                 edje_object_part_swallow(cell->base, key, ic);
+                 evas_object_show(ic);
+                 elm_widget_sub_object_add(cell->wd->self, ic);
+              }
+         }
+     }
+
+   if (cell->gcc->func.state_get)
+     {
+       const Eina_List *l;
+       const char *key;
+
+       cell->states = _elm_stringlist_get(edje_object_data_get(cell->base,
+                                                               "states"));
+       EINA_LIST_FOREACH(cell->states, l, key)
+         {
+            Eina_Bool on = cell->gcc->func.state_get(cell->data,
+                  cell->wd->self, l->data);
+            if (on)
+              {
+                 snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
+                 edje_object_signal_emit(cell->base, buf, "elm");
+              }
+         }
+     }
+
+   if (!cell->wd->cell_width && !cell->wd->cell_height)
+     {
+       edje_object_size_min_restricted_calc(cell->base,
+             &cell->wd->cell_width, &cell->wd->cell_height,
+             cell->wd->cell_width, cell->wd->cell_height);
+       elm_coords_finger_size_adjust(1, &cell->wd->cell_width,
+                                     1, &cell->wd->cell_height);
+     }
+
+   evas_object_event_callback_add(cell->base, EVAS_CALLBACK_MOUSE_DOWN,
+                                 _mouse_down, cell);
+   evas_object_event_callback_add(cell->base, EVAS_CALLBACK_MOUSE_UP,
+                                 _mouse_up, cell);
+   evas_object_event_callback_add(cell->base, EVAS_CALLBACK_MOUSE_MOVE,
+                                 _mouse_move, cell);
+
+   if (cell->selected)
+     edje_object_signal_emit(cell->base, "elm,state,selected", "elm");
+   if (cell->disabled)
+     edje_object_signal_emit(cell->base, "elm,state,disabled", "elm");
+
+   evas_object_show(cell->base);
+   cell->realized = EINA_TRUE;
+   cell->want_unrealize = EINA_FALSE;
+}
+
+static void
+_cell_unrealize(Elm_Grid_Cell *cell)
+{
+   Evas_Object *icon;
+
+   if (!cell->realized) return;
+   if (cell->long_timer)
+     {
+       ecore_timer_del(cell->long_timer);
+       cell->long_timer = NULL;
+     }
+   evas_object_del(cell->base);
+   cell->base = NULL;
+   evas_object_del(cell->spacer);
+   cell->spacer = NULL;
+   _elm_stringlist_free(cell->labels);
+   cell->labels = NULL;
+   _elm_stringlist_free(cell->icons);
+   cell->icons = NULL;
+   _elm_stringlist_free(cell->states);
+
+   EINA_LIST_FREE(cell->icon_objs, icon)
+      evas_object_del(icon);
+
+   cell->states = NULL;
+   cell->realized = EINA_FALSE;
+   cell->want_unrealize = EINA_FALSE;
+}
+
+static void
+_cell_place(Elm_Grid_Cell *cell, Evas_Coord cx, Evas_Coord cy)
+{
+   Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh;
+   Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
+
+   cell->x = cx;
+   cell->y = cy;
+   evas_object_geometry_get(cell->wd->self, &ox, &oy, &vw, &vh);
+   evas_output_viewport_get(evas_object_evas_get(cell->wd->self),
+                           &cvx, &cvy, &cvw, &cvh);
+
+   /* Preload rows/columns at each side of the Grid */
+   cvx -= PRELOAD * cell->wd->cell_width;
+   cvy -= PRELOAD * cell->wd->cell_height;
+   cvw += 2 * PRELOAD * cell->wd->cell_width;
+   cvh += 2 * PRELOAD * cell->wd->cell_height;
+
+   tch = ((vh/cell->wd->cell_height)*cell->wd->cell_height);
+   alignh = (vh - tch)*cell->wd->align_y;
+
+   tcw = ((vw/cell->wd->cell_width)*cell->wd->cell_width);
+   alignw = (vw - tcw)*cell->wd->align_x;
+
+   if (cell->wd->horizontal && cell->wd->minw < vw)
+     {
+        int columns;
+
+        columns = eina_list_count(cell->wd->cells)/(vh/cell->wd->cell_height);
+        if (eina_list_count(cell->wd->cells) % (vh/cell->wd->cell_height))
+             columns++;
+
+        tcw = cell->wd->cell_width * columns;
+       alignw = (vw - tcw)*cell->wd->align_x;
+     }
+   else if (cell->wd->horizontal && cell->wd->minw > vw)
+        alignw = 0;   
+   if (!cell->wd->horizontal && cell->wd->minh < vh)
+     {
+        int rows;
+
+        rows = eina_list_count(cell->wd->cells)/(vw/cell->wd->cell_width);
+        if (eina_list_count(cell->wd->cells) % (vw/cell->wd->cell_width))
+             rows++;
+
+        tch = cell->wd->cell_height * rows;
+        alignh = (vh - tch)*cell->wd->align_y;
+     }
+   else if (!cell->wd->horizontal && cell->wd->minh > vh)
+        alignh = 0;
+   x = cx * cell->wd->cell_width - cell->wd->pan_x + ox + alignw;
+   y = cy * cell->wd->cell_height - cell->wd->pan_y + oy + alignh;
+
+   if (ELM_RECTS_INTERSECT(x, y, cell->wd->cell_width, cell->wd->cell_height,
+                          cvx, cvy, cvw, cvh))
+     {
+       Eina_Bool was_realized = cell->realized;
+       _cell_realize(cell);
+       if (!was_realized)
+         evas_object_smart_callback_call(cell->wd->self, "realized", cell);
+       evas_object_move(cell->base, x, y);
+       evas_object_resize(cell->base, cell->wd->cell_width,
+                          cell->wd->cell_height);
+     }
+   else
+     _cell_unrealize(cell);
+}
+
+static Elm_Grid_Cell *
+_cell_create(Widget_Data *wd, const Elm_Grid_Cell_Class *gcc,
+      const void *data, Evas_Smart_Cb func, const void *func_data)
+{
+   Elm_Grid_Cell *cell;
+
+   cell = calloc(1, sizeof(*cell));
+   if (!cell) return NULL;
+   cell->wd = wd;
+   cell->gcc = gcc;
+   cell->data = data;
+   cell->func.func = func;
+   cell->func.data = func_data;
+   return cell;
+}
+
+static void
+_cell_del(Elm_Grid_Cell *cell)
+{
+   if (cell->selected)
+     cell->wd->selected = eina_list_remove(cell->wd->selected, cell);
+   if (cell->realized) _cell_unrealize(cell);
+   if ((!cell->delete_me) && (cell->gcc->func.del))
+     cell->gcc->func.del(cell->data, cell->wd->self);
+   cell->delete_me = EINA_TRUE;
+   cell->wd->cells = eina_list_remove(cell->wd->cells, cell);
+   if (cell->long_timer) ecore_timer_del(cell->long_timer);
+   free(cell);
+}
+
+static void
+_cell_select(Elm_Grid_Cell *cell)
+{
+   if ((cell->wd->no_select) || (cell->delete_me)) return;
+   if (cell->selected)
+     {
+       if (cell->wd->always_select) goto call;
+       return;
+     }
+   cell->selected = EINA_TRUE;
+   cell->wd->selected = eina_list_append(cell->wd->selected, cell);
+call:
+   cell->walking++;
+   if (cell->func.func) cell->func.func((void *)cell->func.data, cell->wd->self,
+                                       cell);
+   if (!cell->delete_me)
+     evas_object_smart_callback_call(cell->wd->self, "selected", cell);
+   cell->walking--;
+   if ((cell->walking == 0) && (cell->delete_me))
+     if (cell->relcount == 0) _cell_del(cell);
+}
+
+static void
+_cell_unselect(Elm_Grid_Cell *cell)
+{
+   if ((cell->delete_me) || (!cell->hilighted)) return;
+   edje_object_signal_emit(cell->base, "elm,state,unselected", "elm");
+   cell->hilighted = EINA_FALSE;
+   if (cell->selected)
+     {
+       cell->selected = EINA_FALSE;
+       cell->wd->selected = eina_list_remove(cell->wd->selected, cell);
+       evas_object_smart_callback_call(cell->wd->self, "unselected", cell);
+     }
+}
+
+static void
+_calc_job(void *data)
+{
+   Widget_Data *wd = data;
+   Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
+   int count;
+
+   evas_output_viewport_get(evas_object_evas_get(wd->self), NULL, NULL,
+                           &cvw, &cvh);
+   if (wd->horizontal && wd->cell_height)
+     nmax = cvh / wd->cell_height;
+   else if (wd->cell_width)
+     nmax = cvw / wd->cell_width;
+
+   if (nmax)
+     {
+       count = eina_list_count(wd->cells);
+       if (wd->horizontal)
+         {
+            minw = ceil(count  / (float)nmax) * wd->cell_width;
+            minh = nmax * wd->cell_height;
+         }
+       else
+         {
+            minw = nmax * wd->cell_width;
+            minh = ceil(count / (float)nmax) * wd->cell_height;
+         }
+     }
+
+   if ((minw != wd->minw) || (minh != wd->minh))
+     {
+       wd->minh = minh;
+       wd->minw = minw;
+       evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
+       _sizing_eval(wd->self);
+     }
+
+   wd->nmax = nmax;
+   wd->calc_job = NULL;
+   evas_object_smart_changed(wd->pan_smart);
+}
+
+static void
+_pan_add(Evas_Object *obj)
+{
+   Pan *sd;
+   Evas_Object_Smart_Clipped_Data *cd;
+
+   _pan_sc.add(obj);
+   cd = evas_object_smart_data_get(obj);
+   sd = ELM_NEW(Pan);
+   if (!sd) return;
+   sd->__clipped_data = *cd;
+   free(cd);
+   evas_object_smart_data_set(obj, sd);
+}
+
+static void
+_pan_del(Evas_Object *obj)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+
+   if (!sd) return;
+   _pan_sc.del(obj);
+}
+
+static void
+_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
+   sd->wd->pan_x = x;
+   sd->wd->pan_y = y;
+   evas_object_smart_changed(obj);
+}
+
+static void
+_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if (x) *x = sd->wd->pan_x;
+   if (y) *y = sd->wd->pan_y;
+}
+
+static void
+_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if (w) *w = sd->wd->minw;
+   if (h) *h = sd->wd->minh;
+}
+
+static void
+_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   Evas_Coord ow, oh;
+
+   if (!sd) return;
+   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
+   if (x)
+     *x = (ow < sd->wd->minw) ? sd->wd->minw - ow : 0;
+   if (y)
+     *y = (oh < sd->wd->minh) ? sd->wd->minh - oh : 0;
+}
+
+static void
+_pan_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   Evas_Coord ow, oh;
+
+   evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
+   if ((ow == w) && (oh == h)) return;
+   if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
+   sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
+}
+
+static void
+_pan_calculate(Evas_Object *obj)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   Evas_Coord cx = 0, cy = 0;
+   Eina_List *l;
+   Elm_Grid_Cell *cell;
+
+   if (!sd) return;
+   if (!sd->wd->nmax) return;
+
+   EINA_LIST_FOREACH(sd->wd->cells, l, cell)
+     {
+       _cell_place(cell, cx, cy);
+       if (sd->wd->horizontal)
+         {
+            cy = (cy + 1) % sd->wd->nmax;
+            if (!cy) cx++;
+         }
+       else
+         {
+            cx = (cx + 1) % sd->wd->nmax;
+            if (!cx) cy++;
+         }
+     }
+}
+
+static void
+_pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
+{
+   Pan *sd = evas_object_smart_data_get(obj);
+   if (!sd) return;
+   if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
+   sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
+}
+
+static void
+_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_hold_set(wd->scr, 1);
+}
+
+static void
+_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_hold_set(wd->scr, 0);
+}
+
+static void
+_freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_freeze_set(wd->scr, 1);
+}
+
+static void
+_freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_freeze_set(wd->scr, 0);
+}
+
+static void
+_scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "scroll,drag,start", NULL);
+}
+
+static void
+_scr_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "scroll,drag,stop", NULL);
+}
+
+static void
+_scr_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   evas_object_smart_callback_call(data, "scroll", NULL);
+}
+
+/**
+ * Add a new Scrolled Grid object.
+ *
+ * @param parent The parent object.
+ * @return  The new object or NULL if it cannot be created.
+ *
+ * @see elm_scrolled_grid_cell_size_set()
+ * @see elm_scrolled_grid_horizontal_set()
+ * @see elm_scrolled_grid_cell_add()
+ * @see elm_scrolled_grid_cell_del()
+ * @see elm_scrolled_grid_clear()
+ *
+ * @ingroup Grid
+ */
+EAPI Evas_Object *
+elm_scrolled_grid_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Evas_Coord minw, minh;
+   Widget_Data *wd;
+   static Evas_Smart *smart = NULL;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "grid");
+   elm_widget_type_set(obj, "grid");
+   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);
+
+   wd->scr = elm_smart_scroller_add(e);
+   elm_smart_scroller_widget_set(wd->scr, obj);
+   elm_smart_scroller_object_theme_set(obj, wd->scr, "grid", "base", "default");
+   elm_widget_resize_object_set(obj, wd->scr);
+
+   evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
+   evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
+   evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
+
+   elm_smart_scroller_bounce_allow_set(wd->scr, 1, 1);
+
+   wd->self = obj;
+   wd->align_x = 0.5;
+   wd->align_y = 0.5;
+
+   evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
+   evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
+
+   if (!smart)
+     {
+       static Evas_Smart_Class sc;
+
+       evas_object_smart_clipped_smart_set(&_pan_sc);
+       sc = _pan_sc;
+       sc.name = "elm_scrolled_grid_pan";
+       sc.version = EVAS_SMART_CLASS_VERSION;
+       sc.add = _pan_add;
+       sc.del = _pan_del;
+       sc.resize = _pan_resize;
+       sc.move = _pan_move;
+       sc.calculate = _pan_calculate;
+       smart = evas_smart_class_new(&sc);
+     }
+   if (smart)
+     {
+       wd->pan_smart = evas_object_smart_add(e, smart);
+       wd->pan = evas_object_smart_data_get(wd->pan_smart);
+       wd->pan->wd = wd;
+     }
+
+   elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
+                                    _pan_set, _pan_get,
+                                    _pan_max_get, _pan_child_size_get);
+
+   _sizing_eval(obj);
+
+   return obj;
+}
+
+/**
+ * Set the size for the cell of the Grid.
+ *
+ * @param obj The Grid object.
+ * @param w The cell's width.
+ * @param h The cell's height;
+ *
+ * @see elm_scrolled_grid_cell_size_get()
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_cell_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->cell_width == w && wd->cell_height == h) return;
+   wd->cell_width = w;
+   wd->cell_height = h;
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+}
+
+/**
+ * Get the size of the cell of the Grid.
+ *
+ * @param obj The Grid object.
+ * @param w Pointer to the cell's width.
+ * @param h Pointer to the cell's height.
+ *
+ * @see elm_scrolled_grid_cell_size_get()
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_cell_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (w) *w = wd->cell_width;
+   if (h) *h = wd->cell_height;
+}
+
+/**
+ * Set cell's alignment within the scroller.
+ *
+ * @param obj The grid object.
+ * @param align_x The x alignment (0 <= x <= 1).
+ * @param align_y The y alignment (0 <= y <= 1).
+ *
+ * @see elm_scrolled_grid_align_get()
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_align_set(Evas_Object *obj, double align_x, double align_y)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (align_x > 1.0)
+     align_x = 1.0;
+   else if (align_x < 0.0)
+     align_x = 0.0;
+   wd->align_x = align_x;
+
+   if (align_y > 1.0)
+     align_y = 1.0;
+   else if (align_y < 0.0)
+     align_y = 0.0;
+   wd->align_y = align_y;
+}
+
+/**
+ * Get the alignenment set for the grid object.
+ *
+ * @param obj The grid object.
+ * @param align_x Pointer to x alignenment.
+ * @param align_y Pointer to y alignenment.
+ *
+ * @see elm_scrolled_grid_align_set()
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_align_get(const Evas_Object *obj, double *align_x, double *align_y)
+{
+    ELM_CHECK_WIDTYPE(obj, widtype);
+    Widget_Data *wd = elm_widget_data_get(obj);
+    if (align_x) *align_x = wd->align_x;
+    if (align_y) *align_y = wd->align_y;
+}
+
+/**
+ * Add cell to the end of the Grid.
+ *
+ * @param obj The Grid object.
+ * @param gcc The cell class for the cell.
+ * @param data The cell data.
+ * @param func Convenience function called when cell is selected.
+ * @param func_data Data passed to @p func above.
+ * @return A handle to the cell added or NULL if not possible.
+ *
+ * @see elm_scrolled_grid_cell_del()
+ *
+ * @ingroup Grid
+ */
+EAPI Elm_Grid_Cell *
+elm_scrolled_grid_cell_add(Evas_Object *obj, const Elm_Grid_Cell_Class *gcc,
+                          const void *data, Evas_Smart_Cb func,
+                          const void *func_data)
+{
+   Elm_Grid_Cell *cell;
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   cell = _cell_create(wd, gcc, data, func, func_data);
+   if (!cell) return NULL;
+
+   wd->cells = eina_list_append(wd->cells, cell);
+   wd->no_select = EINA_FALSE;
+
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+
+   return cell;
+}
+
+/**
+ * Remove a cell from the Grid.
+ *
+ * @param cell The cell to be removed.
+ * @return @c EINA_TRUE on success or @c EINA_FALSE otherwise.
+ *
+ * @see elm_scrolled_grid_clear() to remove all cells of the grid.
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_cell_del(Elm_Grid_Cell *cell)
+{
+   if (!cell) return;
+   if ((cell->relcount > 0) || (cell->walking > 0))
+     {
+       cell->delete_me = EINA_TRUE;
+       if (cell->selected)
+         cell->wd->selected = eina_list_remove(cell->wd->selected, cell);
+       if (cell->gcc->func.del) cell->gcc->func.del(cell->data, cell->wd->self);
+       return;
+     }
+
+   _cell_del(cell);
+
+   if (cell->wd->calc_job) ecore_job_del(cell->wd->calc_job);
+   cell->wd->calc_job = ecore_job_add(_calc_job, cell->wd);
+}
+
+/**
+ * Set for what direction the grid will expand.
+ *
+ * @param obj The Grid object.
+ * @param setting If @c EINA_TRUE the grid will expand horizontally or
+ * vertically if @c EINA_FALSE.
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_horizontal_set(Evas_Object *obj, Eina_Bool setting)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (setting == wd->horizontal) return;
+   wd->horizontal = setting;
+
+   /* Update the cells to conform to the new layout */
+   if (wd->calc_job) ecore_job_del(wd->calc_job);
+   wd->calc_job = ecore_job_add(_calc_job, wd);
+}
+
+/**
+ * Clear the Grid
+ *
+ * This clears all cells in the grid, leaving it empty.
+ *
+ * @param obj The Grid object.
+ *
+ * @see elm_scrolled_grid_cell_del() to remove just one cell.
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_clear(Evas_Object *obj)
+{
+   Eina_List *l, *l_next;
+   Elm_Grid_Cell *cell;
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->calc_job)
+     {
+       ecore_job_del(wd->calc_job);
+       wd->calc_job = NULL;
+     }
+
+   EINA_LIST_FOREACH_SAFE(wd->cells, l, l_next, cell)
+     {
+       if (cell->realized) _cell_unrealize(cell);
+       if (cell->gcc->func.del) cell->gcc->func.del(cell->data, wd->self);
+       if (cell->long_timer) ecore_timer_del(cell->long_timer);
+       free(cell);
+       wd->cells = eina_list_remove_list(wd->cells, l);
+     }
+
+   if (wd->selected)
+     {
+       eina_list_free(wd->selected);
+       wd->selected = NULL;
+     }
+
+   wd->pan_x = 0;
+   wd->pan_y = 0;
+   wd->minw = 0;
+   wd->minh = 0;
+   evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
+   evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
+   _sizing_eval(obj);
+}
+
+/**
+ * Get the real evas object of the grid cell
+ *
+ * This returns the actual evas object used for the specified grid cell.
+ * This may be NULL as it may not be created, and may be deleted at any time
+ * by grid. Do not modify this object (move, resize, show, hide etc.) as grid
+ * is controlling it. This function is for querying, emitting custom signals
+ * or hooking lower level callbacks for events. Do not delete this object
+ * under any circumstances.
+ *
+ * @param cell The Grid cell.
+ * @return the evas object associated to this cell.
+ *
+ * @see elm_scrolled_grid_cell_data_get()
+ *
+ * @ingroup Grid
+ */
+EAPI const Evas_Object *
+elm_scrolled_grid_cell_object_get(Elm_Grid_Cell *cell)
+{
+   if (!cell) return NULL;
+   return cell->base;
+}
+
+/**
+ * Returns the data associated to a cell
+ *
+ * This returns the data value passed on the elm_scrolled_grid_cell_add() and
+ * related cell addition calls.
+ *
+ * @param cell The Grid cell.
+ * @return the data associated to this cell.
+ *
+ * @see elm_scrolled_grid_cell_add()
+ * @see elm_scrolled_grid_cell_object_get()
+ *
+ * @ingroup Grid
+ */
+EAPI void *
+elm_scrolled_grid_cell_data_get(Elm_Grid_Cell *cell)
+{
+   if (!cell) return NULL;
+   return (void *)cell->data;
+}
+
+/**
+ * Get the cell's coordinates.
+ *
+ * This returns the logical position of the cell whithin the Grid.
+ *
+ * @param cell The Grid cell.
+ * @param x The x-axis coordinate pointer.
+ * @param y The y-axis coordinate pointer.
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_cell_pos_get(const Elm_Grid_Cell *cell, unsigned int *x, unsigned int *y)
+{
+   if (!cell) return;
+   if (x) *x = cell->x;
+   if (y) *y = cell->y;
+}
+
+/**
+ * Enable or disable multi-select in the grid.
+ *
+ * This enables (EINA_TRUE) or disables (EINA_FALSE) multi-select in the grid.
+ * This allows more than 1 cell to be selected.
+ *
+ * @param obj The grid object.
+ * @param multi Multi-select enabled/disabled
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_multi_select_set(Evas_Object *obj, Eina_Bool multi)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->multi = multi;
+}
+
+/**
+ * Get if multi-select in grid is enabled or disabled
+ *
+ * @param obj The grid object
+ * @return Multi-select enable/disable
+ * (EINA_TRUE = enabled / EINA_FALSE = disabled)
+ *
+ * @ingroup Grid
+ */
+EAPI Eina_Bool
+elm_scrolled_grid_multi_select_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return wd->multi;
+}
+
+/**
+ * Get the selected cell in the grid
+ *
+ * This gets the selected cell in the grid (if multi-select is enabled only
+ * the first cell in the list is selected - which is not very useful, so see
+ * elm_scrolled_grid_selected_cells_get() for when multi-select is used).
+ *
+ * If no cell is selected, NULL is returned.
+ *
+ * @param obj The grid object.
+ * @return The selected cell, or NULL if none.
+ *
+ * @ingroup Grid
+ */
+EAPI Elm_Grid_Cell *
+elm_scrolled_grid_selected_cell_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   if (wd->selected) return wd->selected->data;
+   return NULL;
+}
+
+/**
+ * Get a list of selected cells in the grid.
+ *
+ * This returns a list of the selected cells. This list pointer is only valid
+ * so long as no cells are selected or unselected (or unselected implictly by
+ * deletion). The list contains Elm_Grid_Cell pointers.
+ *
+ * @param obj The grid object.
+ * @return The list of selected cells, or NULL if none are selected.
+ *
+ * @ingroup Grid
+ */
+EAPI const Eina_List *
+elm_scrolled_grid_selected_cells_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return wd->selected;
+}
+
+/**
+ * Get the selected state of a cell.
+ *
+ * This gets the selected state of a cell (1 selected, 0 not selected).
+ *
+ * @param cell The cell
+ * @return The selected state
+ *
+ * @ingroup Grid
+ */
+EAPI Eina_Bool
+elm_scrolled_grid_cell_selected_get(const Elm_Grid_Cell *cell)
+{
+   if (!cell) return EINA_FALSE;
+   return cell->selected;
+}
+
+/**
+ * Sets the disabled state of a cell.
+ *
+ * A disabled cell cannot be selected or unselected. It will also change
+ * appearance to disabled. This sets the disabled state (1 disabled, 0 not
+ * disabled).
+ *
+ * @param cell The cell
+ * @param disabled The disabled state
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_cell_disabled_set(Elm_Grid_Cell *cell, Eina_Bool disabled)
+{
+   if (!cell) return;
+   if (cell->disabled == disabled) return;
+   if (cell->delete_me) return;
+   cell->disabled = disabled;
+   if (cell->realized)
+     {
+       if (cell->disabled)
+         edje_object_signal_emit(cell->base, "elm,state,disabled", "elm");
+       else
+         edje_object_signal_emit(cell->base, "elm,state,enabled", "elm");
+     }
+}
+
+/**
+ * Get the disabled state of a cell.
+ *
+ * This gets the disabled state of the given cell.
+ *
+ * @param cell The cell
+ * @return The disabled state
+ *
+ * @ingroup Grid
+ */
+EAPI Eina_Bool
+elm_scrolled_grid_cell_disabled_get(const Elm_Grid_Cell *cell)
+{
+   if (!cell) return EINA_FALSE;
+   if (cell->delete_me) return EINA_FALSE;
+   return cell->disabled;
+}
+
+/**
+ * Set the always select mode.
+ *
+ * Cells will only call their selection func and callback when first becoming
+ * selected. Any further clicks will do nothing, unless you enable always select
+ * with elm_scrolled_grid_always_select_mode_set(). This means even if selected,
+ * every click will make the selected callbacks be called.
+ *
+ * @param obj The grid object
+ * @param always_select The always select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_always_select_mode_set(Evas_Object *obj, Eina_Bool always_select)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->always_select = always_select;
+}
+
+/**
+ * Get the always select mode.
+ *
+ * @param obj The grid object.
+ * @return The always select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Grid
+ */
+EAPI Eina_Bool
+elm_scrolled_grid_always_select_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return wd->always_select;
+}
+
+/**
+ * Set no select mode.
+ *
+ * This will turn off the ability to select items entirely and they will
+ * neither appear selected nor call selected callback functions.
+ *
+ * @param obj The grid object
+ * @param no_select The no select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->no_select = no_select;
+}
+
+/**
+ * Gets no select mode.
+ *
+ * @param obj The grid object
+ * @return The no select mode (EINA_TRUE = on, EINA_FALSE = off)
+ *
+ * @ingroup Grid
+ */
+EAPI Eina_Bool
+elm_scrolled_grid_no_select_mode_get(const Evas_Object *obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return EINA_FALSE;
+   return wd->no_select;
+}
+
+/**
+ * Set bounce mode.
+ *
+ * This will enable or disable the scroller bounce mode for the grid. See
+ * elm_scroller_bounce_set() for details.
+ *
+ * @param obj The grid object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
+}
+
+/**
+ * Get the bounce mode
+ *
+ * @param obj The grid object
+ * @param h_bounce Allow bounce horizontally
+ * @param v_bounce Allow bounce vertically
+ *
+ * @ingroup Grid
+ */
+EAPI void
+elm_scrolled_grid_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
+}
diff --git a/src/lib/elm_softkey.c b/src/lib/elm_softkey.c
new file mode 100644 (file)
index 0000000..d61985c
--- /dev/null
@@ -0,0 +1,1584 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Softkey Softkey
+ * @ingroup Elementary
+ *
+ * This is a softkey
+ */
+
+/**
+ * internal data structure of softkey object
+ */
+#define BTN_ANIMATOR_MAX       4
+#define PANEL_ANIMATOR_MAX     1
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *lay;
+   Evas_Object *button[2];
+   Evas_Object *bg_rect;
+   Evas_Object *panel;
+   Evas_Object *glow_obj;
+
+   Evas_Coord x, y, w, h;
+   Evas_Coord glow_w, glow_h;
+   Evas_Coord win_h;
+   Evas_Coord panel_height;
+   Ecore_Animator *animator;
+   Eina_List *items;
+   unsigned int panel_btn_idx;
+   Eina_Bool button_show[2];
+   Eina_Bool show_panel :1;
+   Eina_Bool animating :1;
+   Eina_Bool is_horizontal;
+   double scale_factor;
+   int max_button;
+   Eina_Bool panel_suppported;
+};
+
+struct _Elm_Softkey_Item
+{
+   Evas_Object *obj;
+   Evas_Object *base;
+   Evas_Object *icon;
+   const char *label;
+   void
+   (*func)(void *data, Evas_Object *obj, void *event_info);
+   const void *data;
+   Eina_Bool disabled :1;
+};
+
+static void
+_item_disable(Elm_Softkey_Item *it, Eina_Bool disabled);
+static void
+_del_hook(Evas_Object *obj);
+static void
+_theme_hook(Evas_Object *obj);
+static void
+_sizing_eval(Evas_Object *obj);
+static void
+_sub_del(void *data, Evas_Object *obj, void *event_info);
+
+/*
+ * callback functions
+ */
+static void
+_softkey_down_cb(void *data, Evas_Object *obj, const char *emission,
+                 const char *source);
+static void
+_softkey_up_cb(void *data, Evas_Object *obj, const char *emission,
+               const char *source);
+
+static void
+_panel_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void
+_panel_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static void
+_more_btn_click_cb(void *data, Evas_Object *obj, const char *emission,
+                   const char *source);
+static void
+_close_btn_click_cb(void *data, Evas_Object *obj, const char *emission,
+                    const char *source);
+static void
+_bg_click_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static Eina_Bool
+_show_button_animator_cb(void *data);
+static Eina_Bool
+_hide_button_animator_cb(void *data);
+static Eina_Bool
+_panel_up_animator_cb(void *data);
+static Eina_Bool
+_panel_down_animator_cb(void *data);
+
+/*
+ * internal function
+ */
+static int
+_show_button(Evas_Object *obj, Elm_Softkey_Type type, Eina_Bool show);
+static int
+_delete_button(Evas_Object *obj);
+
+static void
+_softkey_object_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void
+_softkey_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void
+_softkey_object_show(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void
+_softkey_object_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void
+_softkey_horizontal_set(Evas_Object *obj, Eina_Bool horizontal_mode);
+static void
+_icon_disable(Evas_Object *icon, Eina_Bool disabled)
+{
+   Evas_Object *edj;
+
+   if (!icon) return;
+   edj = elm_layout_edje_get(icon);
+
+   if (disabled)
+     {
+        if (!edj)
+           edje_object_signal_emit(icon, "elm,state,disabled", "elm");
+        else
+           edje_object_signal_emit(edj, "elm,state,disabled", "elm");
+     }
+   else
+     {
+        if (!edj)
+           edje_object_signal_emit(icon, "elm,state,enabled", "elm");
+        else
+           edje_object_signal_emit(edj, "elm,state,enabled", "elm");
+     }
+}
+
+static void
+_item_disable(Elm_Softkey_Item *it, Eina_Bool disabled)
+{
+   Widget_Data *wd = elm_widget_data_get(it->obj);
+   if (!wd) return;
+   if (it->disabled == disabled) return;
+   it->disabled = disabled;
+   if (it->disabled)
+      edje_object_signal_emit(it->base, "elm,state,disabled", "elm");
+   else
+      edje_object_signal_emit(it->base, "elm,state,enabled", "elm");
+
+   _icon_disable(it->icon, disabled);
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+   int i;
+   Evas_Object *btn;
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE,
+                                  _softkey_object_resize);
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_MOVE, _softkey_object_move);
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _softkey_object_show);
+   evas_object_event_callback_del(obj, EVAS_CALLBACK_HIDE, _softkey_object_hide);
+
+   /* delete button */
+   for (i = 0; i < 2; i++)
+     {
+        btn = wd->button[i];
+        if (btn != NULL)
+          {
+             //_delete_button(btn);
+             evas_object_del(wd->button[i]);
+             wd->button[i] = NULL;
+          }
+     }
+
+   //evas_object_smart_callback_del(obj, "sub-object-del", _sub_del);
+
+
+   /* delete panel */
+   if (wd->panel)
+     {
+        elm_softkey_panel_del(obj);
+     }
+
+   /* delete glow effect image */
+   if (wd->glow_obj)
+     {
+        evas_object_del(wd->glow_obj);
+        wd->glow_obj = NULL;
+     }
+   if (wd->lay)
+     {
+        evas_object_del(wd->lay);
+        wd->lay = NULL;
+     }
+
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+   Elm_Softkey_Item* item;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Elm_Softkey_Item *it;
+   const Eina_List *l;
+
+   if (!wd) return;
+
+   _elm_theme_object_set(obj, wd->lay, "softkey", "bg",
+                         elm_widget_style_get(obj));
+   _elm_theme_object_set(obj, wd->glow_obj, "softkey", "glow", "default");
+
+   if (wd->button[ELM_SK_LEFT_BTN])
+     {
+        item = evas_object_data_get(wd->button[ELM_SK_LEFT_BTN], "item_data");
+        _elm_theme_object_set(obj, wd->button[ELM_SK_LEFT_BTN], "softkey",
+                              "button_left", elm_widget_style_get(obj));
+
+        elm_softkey_item_label_set(item, item->label);
+
+     }
+
+   if (wd->button[ELM_SK_RIGHT_BTN])
+     {
+
+        item = evas_object_data_get(wd->button[ELM_SK_RIGHT_BTN], "item_data");
+
+        _elm_theme_object_set(obj, wd->button[ELM_SK_RIGHT_BTN], "softkey",
+                              "button_right", elm_widget_style_get(obj));
+
+        elm_softkey_item_label_set(item, item->label);
+
+     }
+
+   if (wd->panel)
+     {
+        _elm_theme_object_set(obj, wd->panel, "softkey", "panel",
+                              elm_widget_style_get(obj));
+        if (wd->panel_btn_idx > 0)
+          {
+             //show more button
+             edje_object_signal_emit(wd->lay, "more_btn_show", "");
+             EINA_LIST_FOREACH (wd->items, l, it)
+               {
+                  _elm_theme_object_set(obj, it->base, "softkey", "panel_button",
+                                        elm_widget_style_get(obj));
+                  if (it->label)
+                    {
+                       edje_object_part_text_set(it->base, "elm.text", it->label); // set text
+                    }
+               }
+          }
+     }
+
+   _sizing_eval(obj);
+}
+
+static void
+_sub_del(void *data, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *sub = event_info;
+   const Eina_List *l;
+   Elm_Softkey_Item *it;
+   if (!wd) return;
+
+   EINA_LIST_FOREACH(wd->items, l, it)
+     {
+        if (sub == it->icon)
+          {
+             it->icon = NULL;
+          }
+        break;
+     }
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+
+   if (!wd) return;
+
+   _softkey_object_move(obj, NULL, obj, NULL);
+   _softkey_object_resize(obj, NULL, obj, NULL);
+}
+
+static Eina_Bool
+_panel_up_animator_cb(void *data)
+{
+   int max = PANEL_ANIMATOR_MAX;
+   static int progress = 0;
+   Widget_Data *wd;
+   Evas_Coord ypos;
+
+   wd = elm_widget_data_get(data);
+   if (!wd) return 0;
+
+   progress++;
+   wd->animating = EINA_TRUE;
+
+   if (progress > max)
+     {
+        if (!wd->animator) return 0;
+        ecore_animator_del(wd->animator);
+        wd->animator = NULL;
+        wd->animating = EINA_FALSE;
+        wd->show_panel = EINA_TRUE;
+        progress = 0;
+        return 0;
+     }
+
+   /* move up panel */
+   if (wd->panel)
+     {
+        ypos = wd->win_h - (wd->panel_height * progress / max);
+        evas_object_move(wd->panel, wd->x, ypos);
+     }
+
+   return 1;
+}
+
+static Eina_Bool
+_panel_down_animator_cb(void *data)
+{
+   int max = PANEL_ANIMATOR_MAX;
+   static int progress = 0;
+   Widget_Data *wd;
+   Evas_Coord ypos;
+
+   wd = elm_widget_data_get(data);
+   if (!wd) return 0;
+
+   progress++;
+   wd->animating = EINA_TRUE;
+
+   if (progress > max)
+     {
+        if (!wd->animator) return 0;
+        ecore_animator_del(wd->animator);
+        wd->animator = NULL;
+        wd->animating = EINA_FALSE;
+        //wd->animator = ecore_animator_add(_show_button_animator_cb, data);
+        wd->show_panel = EINA_FALSE;
+        progress = 0;
+
+        evas_object_smart_callback_call(data, "panel,hide", NULL);
+
+        return 0;
+     }
+
+   /* move down panel */
+   if (wd->panel)
+     {
+        ypos = wd->win_h - wd->panel_height + (wd->panel_height * progress / max);
+        evas_object_move(wd->panel, wd->x, ypos);
+     }
+
+   return 1;
+}
+
+static Eina_Bool
+_hide_button_animator_cb(void *data)
+{
+   int max = BTN_ANIMATOR_MAX;
+   static int progress = 0;
+   Widget_Data *wd;
+   Evas_Coord btn_w, xpos;
+
+   wd = elm_widget_data_get(data);
+   if (!wd) return 0;
+
+   progress++;
+   wd->animating = EINA_TRUE;
+
+   if (progress > max)
+     {
+        if (!wd->animator) return 0;
+        ecore_animator_del(wd->animator);
+        wd->animating = EINA_FALSE;
+        wd->animator = ecore_animator_add(_panel_up_animator_cb, data);
+        progress = 0;
+        return 0;
+     }
+
+   /* move left button */
+   if (wd->button[ELM_SK_LEFT_BTN])
+     {
+        edje_object_part_geometry_get(wd->button[ELM_SK_LEFT_BTN], "button_rect",
+                                      NULL, NULL, &btn_w, NULL);
+        //evas_object_geometry_get(wd->button[ELM_SK_LEFT_BTN], NULL, NULL, &btn_w, NULL);
+        xpos = wd->x + -1 * btn_w * progress / max;
+        evas_object_move(wd->button[ELM_SK_LEFT_BTN], xpos, wd->y);
+     }
+
+   /* move right button */
+   if (wd->button[ELM_SK_RIGHT_BTN])
+     {
+        edje_object_part_geometry_get(wd->button[ELM_SK_RIGHT_BTN],
+                                      "button_rect", NULL, NULL, &btn_w, NULL);
+        //evas_object_geometry_get(wd->button[ELM_SK_RIGHT_BTN], NULL, NULL, &btn_w, NULL);
+        xpos = (wd->x + wd->w - btn_w) + (btn_w * progress / max);
+        evas_object_move(wd->button[ELM_SK_RIGHT_BTN], xpos, wd->y);
+     }
+
+   return 1;
+}
+
+static Eina_Bool
+_show_button_animator_cb(void *data)
+{
+   int max = BTN_ANIMATOR_MAX;
+   static int progress = 0;
+   Widget_Data *wd;
+   Evas_Coord btn_w, xpos;
+
+   wd = elm_widget_data_get(data);
+   if (!wd) return 0;
+
+   progress++;
+
+   wd->animating = EINA_TRUE;
+
+   if (progress > max)
+     {
+        if (!wd->animator) return 0;
+        ecore_animator_del(wd->animator);
+        wd->animating = EINA_FALSE;
+        progress = 0;
+        return 0;
+     }
+
+   /* move left button */
+   if (wd->button[ELM_SK_LEFT_BTN])
+     {
+        edje_object_part_geometry_get(wd->button[ELM_SK_LEFT_BTN], "button_rect",
+                                      NULL, NULL, &btn_w, NULL);
+        //evas_object_geometry_get(wd->button[ELM_SK_LEFT_BTN], NULL, NULL, &btn_w, NULL);
+        xpos = wd->x + (-1 * btn_w) + (btn_w * progress / max);
+        evas_object_move(wd->button[ELM_SK_LEFT_BTN], xpos, wd->y);
+     }
+
+   /* move right button */
+   if (wd->button[ELM_SK_RIGHT_BTN])
+     {
+        edje_object_part_geometry_get(wd->button[ELM_SK_RIGHT_BTN],
+                                      "button_rect", NULL, NULL, &btn_w, NULL);
+        //evas_object_geometry_get(wd->button[ELM_SK_RIGHT_BTN], NULL, NULL, &btn_w, NULL);
+        xpos = wd->x + wd->w - (btn_w * progress / max);
+        evas_object_move(wd->button[ELM_SK_RIGHT_BTN], xpos, wd->y);
+     }
+
+   return 1;
+}
+
+static void
+_more_btn_click_cb(void *data, Evas_Object *obj, const char *emission,
+                   const char *source)
+{
+   Widget_Data *wd;
+   wd = elm_widget_data_get(data);
+   if (!wd) return;
+
+   evas_object_smart_callback_call(data, "panel,show", NULL);
+
+   if (!wd->panel) return;
+   evas_object_show(wd->panel);
+
+   if (wd->bg_rect)
+     {
+        evas_object_show(wd->bg_rect);
+     }
+
+   /*if (wd->animating == EINA_FALSE) {
+    wd->animator = ecore_animator_add(_hide_button_animator_cb, data);
+    }*/
+   if (wd->animating == EINA_FALSE)
+     {
+        wd->animator = ecore_animator_add(_panel_up_animator_cb, data);
+     }
+}
+
+static void
+_close_panel(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   if (wd->bg_rect)
+     {
+        evas_object_hide(wd->bg_rect);
+     }
+
+   if (!wd->panel) return;
+
+   if (wd->animating == EINA_FALSE)
+     {
+        wd->animator = ecore_animator_add(_panel_down_animator_cb, obj);
+     }
+}
+
+static void
+_bg_click_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   _close_panel(data);
+}
+
+static void
+_close_btn_click_cb(void *data, Evas_Object *obj, const char *emission,
+                    const char *source)
+{
+   _close_panel(data);
+}
+
+static int
+_show_button(Evas_Object *obj, Elm_Softkey_Type type, Eina_Bool show)
+{
+   if (!obj) return -1;
+
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *btn = wd->button[type];
+   if (!btn) return -1;
+
+   /* Make visible button */
+   if (show)
+     {
+        wd->button_show[type] = EINA_TRUE;
+        evas_object_show(btn);
+     }
+   else
+     {
+        wd->button_show[type] = EINA_FALSE;
+        evas_object_hide(btn);
+     }
+
+   return 0;
+}
+
+static int
+_arrange_button(Evas_Object *obj, Elm_Softkey_Type type)
+{
+   Widget_Data *wd;
+   Evas_Coord btn_w = 0;
+   Evas_Object *btn;
+
+   if (!obj) return -1;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return -1;
+
+   btn = wd->button[type];
+   if (!btn) return -1;
+
+   switch (type)
+   {
+   case ELM_SK_LEFT_BTN:
+      evas_object_move(btn, wd->x, wd->y);
+      break;
+   case ELM_SK_RIGHT_BTN:
+      edje_object_part_geometry_get(btn, "button_rect", NULL, NULL, &btn_w,
+                                    NULL);
+      //evas_object_geometry_get(btn, NULL, NULL, &btn_w, NULL);
+      evas_object_move(btn, wd->x + wd->w - btn_w, wd->y);
+      break;
+   default:
+      break;
+   }
+
+   return 0;
+}
+
+static void
+_softkey_up_cb(void *data, Evas_Object *obj, const char *emission,
+               const char *source)
+{
+   Evas_Object *edj = NULL;
+
+   Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
+   elm_softkey_panel_close(it->obj);
+   if (it->icon)
+     {
+        if(!strcmp(evas_object_type_get(it->icon), "edje"))
+          {
+             edj = it->icon;
+          }
+        else if(!strcmp(evas_object_type_get(it->icon), "elm_widget") && !strcmp(elm_widget_type_get(it->icon), "layout"))
+          {
+             edj = elm_layout_edje_get(it->icon);
+          }
+        if (edj) 
+           edje_object_signal_emit(edj, "elm,state,unselected", "elm");
+     }
+
+   if (it->func)
+      it->func((void *) (it->data), it->obj, it);
+   else
+      evas_object_smart_callback_call(it->obj, "clicked", it);
+}
+
+static void
+_softkey_down_cb(void *data, Evas_Object *obj, const char *emission,
+                 const char *source)
+{
+   Evas_Object *edj = NULL;
+
+   Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
+   evas_object_smart_callback_call(it->obj, "press", it);
+
+   if (!it->icon) return;
+   
+   if(!strcmp(evas_object_type_get(it->icon), "edje"))
+     {
+        edj = it->icon;
+     }
+   else if(!strcmp(evas_object_type_get(it->icon), "elm_widget") && !strcmp(elm_widget_type_get(it->icon), "layout"))
+     {
+        edj = elm_layout_edje_get(it->icon);
+     }
+
+   if (edj) 
+      edje_object_signal_emit(edj, "elm,state,selected", "elm");
+}
+
+static void
+_panel_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
+
+   Widget_Data *wd;
+   wd = elm_widget_data_get(it->obj);
+   if (wd == NULL) return;
+
+   /* hide glow effect */
+   if (wd->glow_obj)
+     {
+        evas_object_hide(wd->glow_obj);
+     }
+
+   elm_softkey_panel_close(it->obj);
+
+   if (it->func)
+      it->func((void *) (it->data), it->obj, it);
+   else
+      evas_object_smart_callback_call(it->obj, "clicked", it);
+}
+
+static void
+_panel_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Evas_Coord glow_x, glow_y;
+   Widget_Data *wd;
+
+   Elm_Softkey_Item *it = (Elm_Softkey_Item *) data;
+   wd = elm_widget_data_get(it->obj);
+   if (wd == NULL) return;
+
+   /* show glow effect */
+   if (wd->glow_obj)
+     {
+        Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *) event_info;
+        glow_x = ev->canvas.x - (wd->glow_w / 2);
+        glow_y = ev->canvas.y - (wd->glow_h / 2);
+
+        evas_object_move(wd->glow_obj, glow_x, glow_y);
+        evas_object_show(wd->glow_obj);
+     }
+
+   evas_object_smart_callback_call(it->obj, "press", it);
+}
+
+static int
+_delete_button(Evas_Object *obj)
+{
+   if (!obj) return -1;
+
+   if (obj)
+     {
+        evas_object_del(obj);
+        obj = NULL;
+     }
+
+   return 0;
+}
+
+static void
+_calc_win_height(Widget_Data *wd)
+{
+   wd->win_h = wd->y + wd->h;
+
+   if (wd->bg_rect)
+     {
+        evas_object_resize(wd->bg_rect, wd->w, wd->win_h);
+        evas_object_move(wd->bg_rect, wd->x, 0);
+     }
+
+   if (wd->panel)
+     {
+        if (wd->show_panel)
+          {
+             evas_object_move(wd->panel, wd->x, (wd->win_h - wd->panel_height));
+          }
+        else
+          {
+             evas_object_move(wd->panel, wd->x, wd->win_h);
+          }
+     }
+}
+
+static void
+_softkey_object_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd;
+   int i;
+   Evas_Coord x, y;
+
+   if (!data) return;
+   wd = elm_widget_data_get((Evas_Object *) data);
+   if (!wd) return;
+
+   evas_object_geometry_get(wd->lay, &x, &y, NULL, NULL);
+
+   wd->x = x;
+   wd->y = y;
+
+   evas_object_move(wd->lay, x, y);
+
+   for (i = 0; i < 2; i++)
+     {
+        _arrange_button((Evas_Object *) data, i);
+     }
+
+   _calc_win_height(wd);
+}
+
+static void
+_softkey_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd;
+   Evas_Object *btn;
+   int i;
+   Evas_Coord btn_w;
+   Evas_Coord w, h;
+
+   if (!data) return;
+   wd = elm_widget_data_get((Evas_Object *) data);
+   if (!wd) return;
+
+   evas_object_geometry_get(wd->lay, NULL, NULL, &w, &h);
+
+   wd->w = w;
+   wd->h = h;
+
+   if (!wd->lay) return;
+   evas_object_resize(wd->lay, w, h);
+
+   /* resize button */
+   for (i = 0; i < 2; i++)
+     {
+        btn = wd->button[i];
+        if (btn != NULL)
+          {
+             edje_object_part_geometry_get(btn, "button_rect", NULL, NULL, &btn_w,
+                                           NULL);
+             evas_object_resize(btn, btn_w, h);
+             _arrange_button((Evas_Object *) data, i);
+          }
+     }
+
+   if (wd->w >= wd->win_h)
+     {
+        _softkey_horizontal_set(data, EINA_TRUE);
+     }
+   else
+     {
+        _softkey_horizontal_set(data, EINA_FALSE);
+     }
+   _calc_win_height(wd);
+}
+
+static void
+_softkey_object_show(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = NULL;
+   Evas_Object *btn;
+   int i;
+   if (data == NULL) return;
+   wd = elm_widget_data_get((Evas_Object *) data);
+   if (wd == NULL) return;
+
+   if (wd->lay)
+     {
+        evas_object_show(wd->lay);
+     }
+
+   /* show button */
+   for (i = 0; i < 2; i++)
+     {
+        btn = wd->button[i];
+        if (btn != NULL && wd->button_show[i] == EINA_TRUE)
+          {
+             evas_object_show(btn);
+             //evas_object_clip_set(btn, evas_object_clip_get((Evas_Object *)data));
+          }
+     }
+   if (wd->panel_btn_idx > 0)
+     {
+        /* show more button */
+        edje_object_signal_emit(wd->lay, "more_btn_show", "");
+     }
+}
+
+static void
+_softkey_object_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Widget_Data *wd = NULL;
+   Evas_Object *btn;
+   int i;
+
+   if (data == NULL) return;
+   wd = elm_widget_data_get((Evas_Object *) data);
+   if (wd == NULL) return;
+
+   if (wd->lay)
+     {
+        evas_object_hide(wd->lay);
+     }
+
+   /* hide button */
+   for (i = 0; i < 2; i++)
+     {
+        btn = wd->button[i];
+        if (btn != NULL)
+          {
+             evas_object_hide(btn);
+          }
+     }
+
+   if (wd->panel_btn_idx > 0)
+     {
+        /* hide more button */
+        edje_object_signal_emit(wd->lay, "more_btn_hide", "");
+     }
+}
+
+/**
+ * Add a new softkey to the parent
+
+ * @param[in] parent the parent of the smart object
+ * @return             Evas_Object* pointer of softkey(evas object) or NULL
+ * @ingroup            Softkey 
+ */
+EAPI Evas_Object *
+elm_softkey_add(Evas_Object *parent)
+{
+   Evas_Object *obj = NULL;
+   Widget_Data *wd = NULL;
+   Evas *e;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   if (e == NULL) return NULL;
+   obj = elm_widget_add(e);
+   elm_widget_type_set(obj, "softkey");
+   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);
+
+   /* load background edj */
+   wd->lay = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->lay, "softkey", "bg", "default");
+   if (wd->lay == NULL)
+     {
+        printf("Cannot load bg edj\n");
+        return NULL;
+     }
+   elm_widget_resize_object_set(obj, wd->lay);
+   edje_object_signal_callback_add(wd->lay, "clicked", "more_btn",
+                                   _more_btn_click_cb, obj);
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
+                                  _softkey_object_resize, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
+                                  _softkey_object_move, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW,
+                                  _softkey_object_show, obj);
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
+                                  _softkey_object_hide, obj);
+   wd->is_horizontal = EINA_FALSE;
+   wd->panel_suppported = EINA_TRUE;
+   wd->scale_factor = elm_scale_get();
+   if (wd->scale_factor == 0.0)
+     {
+        wd->scale_factor = 1.0;
+     }
+
+   /* load glow effect */
+   wd->glow_obj = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->glow_obj, "softkey", "glow", "default");
+   evas_object_geometry_get(wd->glow_obj, NULL, NULL, &wd->glow_w, &wd->glow_h);
+   evas_object_resize(wd->glow_obj, wd->glow_w, wd->glow_h);
+
+   // FIXME
+   //evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   wd->button[ELM_SK_LEFT_BTN] = wd->button[ELM_SK_RIGHT_BTN] = NULL;
+   wd->panel = NULL;
+   //_sizing_eval(obj);
+   wd->show_panel = EINA_FALSE;
+   wd->bg_rect = NULL;
+
+   return obj;
+}
+
+static void
+_softkey_horizontal_set(Evas_Object *obj, Eina_Bool horizontal_mode)
+{
+   Widget_Data *wd;
+   char buff[32];
+   if (!obj) return;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   wd->is_horizontal = horizontal_mode;
+   if (wd->panel)
+   {
+      if ((edje_object_data_get(wd->panel, "max_item_count") == NULL)
+               || (edje_object_data_get(wd->panel, "panel_height") == NULL)
+               || (edje_object_data_get(wd->panel, "panel_height_horizontal")
+                        == NULL))
+        {
+           wd->panel_suppported = EINA_FALSE;
+        }
+      else
+         wd->panel_suppported = EINA_TRUE;
+      if (wd->panel_suppported == EINA_TRUE)
+        {
+           if (wd->is_horizontal == EINA_TRUE)
+             {
+                snprintf(buff, sizeof(buff), "button_%d", (wd->panel_btn_idx
+                                                           + wd->max_button));
+                edje_object_signal_emit(wd->panel, buff, "panel_rect");
+                wd->panel_height
+                   = (int) (atoi(edje_object_data_get(wd->panel, buff))
+                            * wd->scale_factor);
+                evas_object_resize(
+                   wd->panel,
+                   wd->w,
+                   ((int) (atoi(
+                            edje_object_data_get(wd->panel,
+                                                 "panel_height_horizontal"))
+                         * wd->scale_factor)));
+             }
+           else
+             {
+                snprintf(buff, sizeof(buff), "button_%d", (wd->panel_btn_idx));
+                edje_object_signal_emit(wd->panel, buff, "panel_rect");
+                wd->panel_height
+                   = (int) (atoi(edje_object_data_get(wd->panel, buff))
+                            * wd->scale_factor);
+                evas_object_resize(
+                   wd->panel,
+                   wd->w,
+                   ((int) (atoi(
+                            edje_object_data_get(wd->panel,
+                                                 "panel_height"))
+                         * wd->scale_factor)));
+             }
+        }
+      _calc_win_height(wd);
+   }
+}
+
+/**
+ * add side button of softkey
+ * @param[in]  obj     softkey object
+ * @param[in]  type softkey button type
+ * @param[in]  icon The icon object to use for the item
+ * @param[in]  label The text label to use for the item
+ * @param[in]  func Convenience function to call when this item is selected
+ * @param[in]  data Data to pass to convenience function
+ * @return     A handle to the item added
+ * 
+ * @ingroup    Softkey  
+ */
+EAPI Elm_Softkey_Item *
+elm_softkey_button_add(Evas_Object *obj, Elm_Softkey_Type type,
+                       Evas_Object *icon, const char *label, void
+                       (*func)(void *data, Evas_Object *obj, void *event_info),
+                       const void *data)
+{
+   Widget_Data *wd;
+   Evas* evas;
+   char button_type[64];
+   Elm_Softkey_Item *it;
+
+   if (!obj) return NULL;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+
+   if (wd->button[type])
+     {
+        printf("already created.\n");
+        return NULL;
+     }
+
+   /* get evas */
+   evas = evas_object_evas_get(obj);
+   if (!evas) return NULL;
+
+   /* set item data */
+   it = ELM_NEW(Elm_Softkey_Item);
+   it->obj = obj;
+   it->func = func;
+   it->data = data;
+   it->label = NULL;
+   it->icon = NULL;
+   /* load button edj */
+   if (wd->button[type] == NULL)
+     {
+        if (type == ELM_SK_LEFT_BTN)
+          {
+             strcpy(button_type, "button_left");
+          }
+        else
+          {
+             strcpy(button_type, "button_right");
+          }
+
+        it->base = wd->button[type] = edje_object_add(evas);
+        if (!wd->button[type])
+          {
+             free(it);
+             return NULL;
+          }
+        _elm_theme_object_set(obj, wd->button[type], "softkey", button_type,
+                              elm_widget_style_get(obj));
+
+        wd->button_show[type] = EINA_TRUE;
+        if (evas_object_visible_get(obj))
+          {
+             evas_object_show(wd->button[type]);
+          }
+        evas_object_smart_member_add(wd->button[type], obj);
+
+        edje_object_signal_callback_add(wd->button[type], "elm,action,down", "",
+                                        _softkey_down_cb, it);
+        edje_object_signal_callback_add(wd->button[type], "elm,action,click", "",
+                                        _softkey_up_cb, it);
+
+        evas_object_clip_set(wd->button[type], evas_object_clip_get(obj));
+        if (wd->panel) evas_object_raise(wd->panel);
+     }
+
+   _sizing_eval(obj);
+
+   elm_softkey_item_label_set(it, label);
+   elm_softkey_item_icon_set(it, icon);
+
+   if (wd->button[type])
+      evas_object_data_set(wd->button[type], "item_data", it);
+   else
+     {
+        if (it->label) eina_stringshare_del(it->label);
+        it->label = NULL;
+        free(it);
+        return NULL;
+     }
+
+   return it;
+}
+
+/**
+ * delete side button of softkey
+ * @param[in]  obj     softkey object
+ * @param[in]  type softkey button type
+ * 
+ * @ingroup    Softkey  
+ */
+EAPI void
+elm_softkey_button_del(Evas_Object *obj, Elm_Softkey_Type type)
+{
+   Widget_Data *wd;
+   Elm_Softkey_Item *it;
+   Evas_Object *btn;
+
+   if (!obj)
+     {
+        printf("Invalid argument: softkey object is NULL\n");
+        return;
+     }
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return;
+
+   btn = wd->button[type];
+   if (!btn) return;
+
+   it = evas_object_data_get(btn, "item_data");
+   //_delete_button(btn);
+   edje_object_signal_callback_del(wd->button[type], "elm,action,down", "",
+                                   _softkey_down_cb);
+   edje_object_signal_callback_del(wd->button[type], "elm,action,click", "",
+                                   _softkey_up_cb);
+   evas_object_del(wd->button[type]);
+   if (it->label) eina_stringshare_del(it->label);
+   if (it->icon) evas_object_del(it->icon);
+   free(it);
+   wd->button[type] = NULL;
+}
+
+/**
+ * show button of softkey
+ * @param[in]  obj     softkey object
+ * @param[in]  type    softkey button type
+ *
+ * @ingroup    Softkey  
+ */
+EAPI void
+elm_softkey_button_show(Evas_Object *obj, Elm_Softkey_Type type)
+{
+   _show_button(obj, type, EINA_TRUE);
+}
+
+/**
+ * hide button of softkey
+ * @param[in]  obj     softkey object
+ * @param[in]  type    softkey button type
+ *
+ * @ingroup    Softkey  
+ */
+EAPI void
+elm_softkey_button_hide(Evas_Object *obj, Elm_Softkey_Type type)
+{
+   _show_button(obj, type, EINA_FALSE);
+}
+
+/**
+ * add item in panel
+ * @param[in]  obj     softkey object
+ * @param[in]  icon The icon object
+ * @param[in]  label The text label to use for the item
+ * @param[in]  func Convenience function to call when this item is selected
+ * @param[in]  data Data to pass to convenience function
+ * @return     A handle to the item added
+ * 
+ * @ingroup    Softkey  
+ */
+EAPI Elm_Softkey_Item *
+elm_softkey_panel_item_add(Evas_Object *obj, Evas_Object *icon,
+                           const char *label, void
+                           (*func)(void *data, Evas_Object *obj,
+                                   void *event_info), const void *data)
+{
+   Widget_Data *wd;
+   Evas *evas;
+   char button_name[32];
+   Evas_Object *btn;
+   Elm_Softkey_Item *it;
+   char buff[PATH_MAX];
+
+   wd = elm_widget_data_get(obj);
+   if (!wd)
+     {
+        printf("Cannot get smart data\n");
+        return NULL;
+     }
+
+   /* get evas */
+   evas = evas_object_evas_get(obj);
+   if (!evas) return NULL;
+
+   if (wd->panel == NULL)
+     {
+        /* create panel */
+        wd->bg_rect = evas_object_rectangle_add(evas);
+        if (!wd->bg_rect) return NULL;
+        evas_object_color_set(wd->bg_rect, 10, 10, 10, 150);
+        evas_object_pass_events_set(wd->bg_rect, 0);
+
+        if (wd->bg_rect)
+          {
+             evas_object_resize(wd->bg_rect, wd->w, wd->win_h);
+             evas_object_event_callback_add(wd->bg_rect, EVAS_CALLBACK_MOUSE_UP,
+                                            _bg_click_cb, obj);
+             evas_object_smart_member_add(wd->bg_rect, obj);
+          }
+
+        wd->panel = edje_object_add(evas);
+        if (!wd->panel) return NULL;
+        _elm_theme_object_set(obj, wd->panel, "softkey", "panel",
+                              elm_widget_style_get(obj));
+
+        evas_object_move(wd->panel, 0, wd->win_h);
+        edje_object_signal_callback_add(wd->panel, "clicked", "close_btn",
+                                        _close_btn_click_cb, obj);
+        evas_object_smart_member_add(wd->panel, obj);
+        if (evas_object_visible_get(obj))
+          {
+             evas_object_show(wd->panel);
+          }
+        wd->panel_height = 0;
+        if ((edje_object_data_get(wd->panel, "max_item_count") == NULL)
+            || (edje_object_data_get(wd->panel, "panel_height") == NULL)
+            || (edje_object_data_get(wd->panel, "panel_height_horizontal")
+                == NULL))
+          {
+             //If this key is not found in data section, then it means the panel won't come.
+             wd->max_button = 0;
+             // delete panel
+             if (wd->panel)
+               {
+                  elm_softkey_panel_del(obj);
+               }
+             wd->panel_suppported = EINA_FALSE;
+             return NULL;
+          }
+        else
+          {
+             wd->max_button = (int) (atoi(edje_object_data_get(wd->panel,
+                                                               "max_item_count")));
+             if (wd->is_horizontal)
+               {
+                  evas_object_resize(
+                     wd->panel,
+                     wd->w,
+                     ((int) (atoi(
+                              edje_object_data_get(wd->panel,
+                                                   "panel_height_horizontal"))
+                           * wd->scale_factor)));
+               }
+             else
+               {
+                  evas_object_resize(
+                     wd->panel,
+                     wd->w,
+                     ((int) (atoi(
+                              edje_object_data_get(wd->panel,
+                                                   "panel_height"))
+                           * wd->scale_factor)));
+               }
+          }
+
+        evas_object_clip_set(wd->panel, evas_object_clip_get(obj));
+     }
+
+   wd->panel_btn_idx++;
+   if (wd->panel_btn_idx >= wd->max_button) return NULL;
+
+   /* set item data */
+   it = ELM_NEW(Elm_Softkey_Item);
+   it->obj = obj;
+   if (label) it->label = eina_stringshare_add(label);
+   it->icon = icon;
+   it->func = func;
+   it->data = data;
+   /* load panel button */
+   it->base = btn = edje_object_add(evas);
+   if (!btn)
+     {
+        if (it->label) eina_stringshare_del(it->label);
+        free(it);
+        wd->panel_btn_idx--;
+        return NULL;
+     }
+   _elm_theme_object_set(obj, btn, "softkey", "panel_button",
+                         elm_widget_style_get(obj));
+
+   edje_object_part_text_set(btn, "elm.text", label); /* set text */
+   //edje_object_message_signal_process(btn);
+
+   if (wd->panel)
+     {
+        /* swallow button */
+        snprintf(button_name, sizeof(button_name), "panel_button_area_%d",
+                 wd->panel_btn_idx);
+        edje_object_part_swallow(wd->panel, button_name, btn);
+
+        if (wd->is_horizontal)
+          {
+             snprintf(buff, sizeof(buff), "button_%d", wd->max_button
+                      + wd->panel_btn_idx);
+             edje_object_signal_emit(wd->panel, buff, "panel_rect");
+             const char* val = edje_object_data_get(wd->panel, buff);
+             if (val)
+                wd->panel_height = (int) (atoi(val) * wd->scale_factor);
+             else
+               {
+                  if (it->label) eina_stringshare_del(it->label);
+                  evas_object_del(it->base);
+                  free(it);
+                  wd->panel_btn_idx--;
+                  return NULL;
+               }
+          }
+        else
+          {
+             snprintf(buff, sizeof(buff), "button_%d", wd->panel_btn_idx);
+             edje_object_signal_emit(wd->panel, buff, "panel_rect");
+             const char* val = edje_object_data_get(wd->panel, buff);
+             if (val)
+                wd->panel_height = (int) (atoi(val) * wd->scale_factor);
+             else
+               {
+                  if (it->label) eina_stringshare_del(it->label);
+                  evas_object_del(it->base);
+                  free(it);
+                  wd->panel_btn_idx--;
+                  return NULL;
+               }
+          }
+     }
+   else
+     {
+        wd->panel_btn_idx--;
+        return NULL;
+     }
+   evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_DOWN,
+                                  _panel_down_cb, it);
+   evas_object_event_callback_add(btn, EVAS_CALLBACK_MOUSE_UP, _panel_up_cb, it);
+   wd->items = eina_list_append(wd->items, it);
+   if (evas_object_visible_get(obj))
+     {
+        /* show more button */
+        edje_object_signal_emit(wd->lay, "more_btn_show", "");
+     }
+   return it;
+}
+
+/**
+ * delete panel
+
+ * @param[in] obj softkey object
+ * @return int 0 (SUCCESS) or -1 (FAIL)
+ *
+ * @ingroup Softkey
+ */
+EAPI int
+elm_softkey_panel_del(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   char button_name[32];
+   Evas_Object *btn;
+   int i;
+   Elm_Softkey_Item *it;
+
+   wd = elm_widget_data_get(obj);
+   if (!wd) return -1;
+   if (wd->panel == NULL) return -1;
+   if (wd->animator)
+     {
+        ecore_animator_del(wd->animator);
+        wd->animator = NULL;
+        wd->animating = EINA_FALSE;
+     }
+   /* delete background */
+   if (wd->bg_rect)
+     {
+        //evas_object_event_callback_del(wd->bg_rect, EVAS_CALLBACK_MOUSE_UP, _bg_click_cb);
+        evas_object_del(wd->bg_rect);
+        wd->bg_rect = NULL;
+     }
+
+   for (i = 1; i <= wd->panel_btn_idx; i++)
+     {
+        snprintf(button_name, sizeof(button_name), "panel_button_area_%d", i);
+        btn = edje_object_part_swallow_get(wd->panel, button_name);
+        //_delete_button(btn);
+        if (btn)
+          {
+             //edje_object_part_unswallow(wd->panel, btn);
+             //evas_object_event_callback_del(btn, EVAS_CALLBACK_MOUSE_DOWN, _panel_down_cb);
+             //evas_object_event_callback_del(btn, EVAS_CALLBACK_MOUSE_UP, _panel_up_cb);
+             evas_object_del(btn);
+          }
+     }
+
+   EINA_LIST_FREE(wd->items, it)
+     {
+        if (it->label) eina_stringshare_del(it->label);
+        it->base = NULL;
+        if (it->icon) it->icon = NULL;
+        free(it);
+     }
+
+   wd->panel_btn_idx = 0;
+   wd->panel_height = 0;
+
+   //hide more button
+   edje_object_signal_emit(wd->lay, "more_btn_hide", "");
+
+   if (wd->panel)
+     {
+        //evas_object_move(wd->panel, 0, wd->win_h);
+        evas_object_clip_unset(wd->panel);
+        evas_object_del(wd->panel);
+        wd->show_panel = EINA_FALSE;
+        wd->panel = NULL;
+     }
+
+   return 0;
+}
+
+/**
+ * sliding up panel if it is closed
+
+ * @param[in] obj softkey object
+ * @return int 0 (SUCCESS) or -1 (FAIL)
+ *
+ * @ingroup Softkey
+ */
+EAPI int
+elm_softkey_panel_open(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   wd = elm_widget_data_get(obj);
+
+   if (!wd) return -1;
+   if (!wd->panel) return -1;
+
+   if (wd->show_panel == EINA_FALSE)
+     {
+        _more_btn_click_cb(obj, NULL, NULL, NULL);
+     }
+
+   return 0;
+}
+
+/**
+ * sliding down panel if it is opened
+
+ * @param[in] obj softkey object
+ * @return int 0 (SUCCESS) or -1 (FAIL)
+ *
+ * @ingroup Softkey
+ */
+EAPI int
+elm_softkey_panel_close(Evas_Object *obj)
+{
+   Widget_Data *wd;
+   wd = elm_widget_data_get(obj);
+   if (!wd) return -1;
+
+   if (wd->panel == NULL) return -1;
+
+   if (wd->show_panel == EINA_TRUE)
+     {
+        _close_btn_click_cb(obj, obj, NULL, NULL);
+     }
+
+   return 0;
+}
+
+/**
+ * Set the icon of an softkey item
+ *
+ * @param[in] it The item to set the icon
+ * @param[in] icon The icon object
+ *
+ * @ingroup Softkey
+ */
+EAPI void
+elm_softkey_item_icon_set(Elm_Softkey_Item *it, Evas_Object *icon)
+{
+   if (!it) return;
+
+   if ((it->icon != icon) && (it->icon))
+     {
+        //elm_widget_sub_object_del(it->obj, it->icon);
+        evas_object_del(it->icon);
+        it->icon = NULL;
+     }
+
+   if ((icon) && (it->icon != icon))
+     {
+        it->icon = icon;
+        //elm_widget_sub_object_add(it->obj, icon);
+        edje_object_part_swallow(it->base, "elm.swallow.icon", icon);
+        edje_object_signal_emit(it->base, "elm,state,icon,visible", "elm");
+        //edje_object_message_signal_process(it->base);
+        _sizing_eval(it->obj);
+     }
+   else
+      it->icon = icon;
+}
+
+/**
+ * Get the icon of an softkey item
+ *
+ * @param[in] it The item to get the icon
+ * @return The icon object
+ *
+ * @ingroup Softkey
+ */
+EAPI Evas_Object *
+elm_softkey_item_icon_get(Elm_Softkey_Item *it)
+{
+   if (!it) return NULL;
+   return it->icon;
+}
+
+/**
+ * Get the text label of an softkey item
+ *
+ * @param[in] it The item to set the label
+ * @param[in] label label
+ *
+ * @ingroup Softkey
+ */
+EAPI void
+elm_softkey_item_label_set(Elm_Softkey_Item *it, const char *label)
+{
+   if (!it) return;
+   if (it->label) eina_stringshare_del(it->label);
+
+   if (label)
+     {
+        it->label = eina_stringshare_add(label);
+        edje_object_signal_emit(it->base, "elm,state,text,visible", "elm");
+
+        /* set text */
+        edje_object_part_text_set(it->base, "elm.text", label == NULL ? ""
+                                  : label);
+     }
+   else
+     {
+        it->label = NULL;
+        edje_object_signal_emit(it->base, "elm,state,text,hidden", "elm");
+     }
+   //edje_object_message_signal_process(it->base);
+}
+
+/**
+ * Set the item callback function 
+ *
+ * @param[in] it Item to set callback function.
+ * @param[in] func callback function pointer.
+ * @param[in] data callback function argument data.
+ *
+ * @ingroup Softkey
+ */
+EAPI void
+elm_softkey_item_callback_set(Elm_Softkey_Item* item, void
+(*func)(void *data, Evas_Object *obj, void *event_info), const void *data)
+{
+   if (!item) return;
+
+   item->func = func;
+   item->data = data;
+}
+
+/**
+ * Get the text label of an softkey item
+ *
+ * @param[in] it The item to get the label
+ * @return The text label of the softkey item
+ *
+ * @ingroup Softkey
+ */
+EAPI const char *
+elm_softkey_item_label_get(Elm_Softkey_Item *it)
+{
+   if (!it) return NULL;
+   return it->label;
+}
+
+EAPI Eina_Bool
+elm_softkey_item_disabled_get(Elm_Softkey_Item *it)
+{
+   if (!it) return EINA_FALSE;
+   return it->disabled;
+}
+
+EAPI void
+elm_softkey_item_disabled_set(Elm_Softkey_Item *it, Eina_Bool disabled)
+{
+   if (!it) return;
+   _item_disable(it, disabled);
+}
diff --git a/src/lib/elm_tab.c b/src/lib/elm_tab.c
new file mode 100644 (file)
index 0000000..08bd66c
--- /dev/null
@@ -0,0 +1,1337 @@
+/*\r
+ * SLP\r
+ * Copyright (c) 2009 Samsung Electronics, Inc.\r
+ * All rights reserved.\r
+ *\r
+ * This software is a confidential and proprietary information\r
+ * of Samsung Electronics, Inc. ("Confidential Information").  You\r
+ * shall not disclose such Confidential Information and shall use\r
+ * it only in accordance with the terms of the license agreement\r
+ * you entered into with Samsung Electronics.\r
+ */\r
+\r
+\r
+/**\r
+ * @addtogroup Tab Tab\r
+ * @ingroup Elementary\r
+ *\r
+ * This is a Tab. It can contain label and icon objects.\r
+ * You can change the location of items.\r
+ */\r
+\r
+\r
+#include <string.h>\r
+#include <math.h>\r
+\r
+#include <Elementary.h>\r
+#include "elm_priv.h"\r
+\r
+#ifndef EAPI\r
+#define EAPI __attribute__ ((visibility("default")))\r
+#endif\r
+\r
+#define MAX_ITEM 8\r
+#define BASIC_SLOT_NUMBER 3\r
+#define KEYDOWN_INTERVAL       0.6\r
+\r
+#define PORTRAIT               0\r
+#define LANDSCAPE              1\r
+#define LANDSCAPE_GAP   10\r
+\r
+#define MAX_ARGS       512\r
+\r
+#define _EDJ(x) (Evas_Object *)elm_layout_edje_get(x)\r
+#define ELM_MAX(v1, v2)    (((v1) > (v2)) ? (v1) : (v2))\r
+\r
+\r
+// internal data structure of tab object\r
+typedef struct _Widget_Data Widget_Data;\r
+\r
+struct _Widget_Data\r
+{\r
+       Evas *evas;\r
+       Evas_Object *object;\r
+       Evas_Object *parent;\r
+       Evas_Object *edje;\r
+       Evas_Object *moving_obj;\r
+       Evas_Object *box[MAX_ITEM];\r
+       Evas_Object *ebx;\r
+\r
+       Evas_Coord x, y, w, h;\r
+\r
+       int cur_first_slot;\r
+       int mode;\r
+       int view_slot_num;\r
+       int tab_down_x;\r
+       int tab_down_y;\r
+       int num;\r
+       int edit_from;\r
+       int edit_to;\r
+       double time;\r
+\r
+       Eina_List *items;\r
+\r
+       Ecore_Timer *timer;\r
+       Eina_Bool flag;\r
+       Eina_Bool edit_disable;\r
+\r
+       Ecore_Event_Handler *move_event;\r
+       Ecore_Event_Handler *up_event;\r
+};\r
+\r
+struct _Elm_Tab_Item\r
+  {\r
+       Evas_Object *obj;\r
+       Evas_Object *base;\r
+       Evas_Object *icon;\r
+       const char *label;\r
+       int slot;\r
+       int badge;\r
+       void (*func)(void *data, Evas_Object *obj, void *event_info);\r
+       const void *data;\r
+       Eina_Bool selected : 1;\r
+  };\r
+\r
+static void _del_hook(Evas_Object *obj);\r
+static void _theme_hook(Evas_Object *obj);\r
+static void _sizing_eval(Evas_Object *obj);\r
+static void _sub_del(void *data, Evas_Object *obj, void *event_info);\r
+\r
+static void _tab_object_move(void *data, Evas *e, Evas_Object *obj, void *event_info);\r
+static void _tab_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);\r
+static void _tab_object_show(void *data, Evas *e, Evas_Object *obj, void *event_info);\r
+static void _tab_object_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);\r
+\r
+static void light_check(Widget_Data *wd);\r
+static void select_check(Widget_Data *wd);\r
+static void edit_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);\r
+static int _selected_box(Elm_Tab_Item *it);\r
+static int _move_obj_to_left(Widget_Data *wd);\r
+static int _move_obj_to_right(Widget_Data *wd);\r
+static void item_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);\r
+static void press_move_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);\r
+static void press_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);\r
+static void press_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);\r
+void tab_item_cb(void *data, Evas_Object *obj, const char *emission, const char *source);\r
+\r
+static void\r
+_del_hook(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       Elm_Tab_Item *item;\r
+\r
+       if (!wd) return;\r
+\r
+       if (wd->edje) {\r
+               evas_object_smart_member_del(wd->edje);\r
+               evas_object_del(wd->edje);\r
+               wd->edje = NULL;\r
+       }\r
+\r
+       EINA_LIST_FREE(wd->items, item){\r
+               eina_stringshare_del(item->label);\r
+               if (item->icon) evas_object_del(item->icon);\r
+               if(item->base) evas_object_del(item->base);\r
+               free(item);\r
+       }\r
+\r
+       if (wd->ebx) {\r
+               evas_object_smart_member_del(wd->ebx);\r
+               evas_object_del(wd->ebx);\r
+               wd->ebx = NULL;\r
+       }\r
+\r
+       free(wd);\r
+}\r
+\r
+static void\r
+_theme_hook(Evas_Object *obj)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       char buf[MAX_ARGS];\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       if(wd->mode == PORTRAIT){\r
+               snprintf(buf, sizeof(buf), "bg_portrait_%d", wd->view_slot_num);\r
+       }else if(wd->mode == LANDSCAPE){\r
+               snprintf(buf, sizeof(buf), "bg_landscape_%d", wd->view_slot_num);\r
+       }\r
+       _elm_theme_object_set(obj, wd->edje, "tab", buf, elm_widget_style_get(obj));\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               _elm_theme_object_set(obj, item->base, "tab", "item", elm_widget_style_get(item->obj));\r
+               if (item->label){\r
+                       edje_object_part_text_set(item->base, "elm.text", item->label);\r
+               }\r
+\r
+               if (item->icon){\r
+       //              int ms = 0;\r
+\r
+       //              ms = ((double)wd->icon_size * _elm_config->scale);\r
+                       evas_object_size_hint_min_set(item->icon, 24, 24);\r
+                       evas_object_size_hint_max_set(item->icon, 40, 40);\r
+                       edje_object_part_swallow(item->base, "elm.swallow.icon", item->icon);\r
+                       evas_object_show(item->icon);\r
+                       elm_widget_sub_object_add(obj, item->icon);\r
+               }\r
+\r
+               if (item->label && item->icon){\r
+                       edje_object_signal_emit(item->base, "elm,state,icon_text", "elm");\r
+               }\r
+       }\r
+       select_check(wd);\r
+}\r
+\r
+static void\r
+_sub_del(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       //Evas_Object *sub = event_info;\r
+       if (!wd) return;\r
+       /*\r
+          if (sub == wd->icon)\r
+          {\r
+          edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");\r
+          evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,\r
+          _changed_size_hints, obj);\r
+          wd->icon = NULL;\r
+          edje_object_message_signal_process(wd->btn);\r
+          _sizing_eval(obj);\r
+          }\r
+          */\r
+}\r
+\r
+static void\r
+_sizing_eval(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+\r
+       if (!wd) return;\r
+\r
+       DBG("[%s]\n", __func__);\r
+\r
+       _tab_object_move(obj, NULL, obj, NULL);\r
+       _tab_object_resize(obj, NULL, obj, NULL);\r
+}\r
+\r
+/**\r
+ * Add a new tab object\r
+ *\r
+ * @param parent The parent object\r
+ * @return The new object or NULL if it cannot be created\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Evas_Object *elm_tab_add(Evas_Object *parent) {\r
+       Evas_Object *obj = NULL;\r
+       Widget_Data *wd = NULL;\r
+       Evas_Coord x, y, w, h;\r
+       char buf[MAX_ARGS];\r
+\r
+       wd = ELM_NEW(Widget_Data);\r
+       wd->evas = evas_object_evas_get(parent);\r
+       if (wd->evas == NULL) return NULL;\r
+       obj = elm_widget_add(wd->evas);\r
+       if(obj == NULL) return NULL;\r
+       elm_widget_type_set(obj, "tab");\r
+       elm_widget_sub_object_add(parent, obj);\r
+       elm_widget_data_set(obj, wd);\r
+       elm_widget_del_hook_set(obj, _del_hook);\r
+       elm_widget_theme_hook_set(obj, _theme_hook);\r
+\r
+       // initialization\r
+       wd->parent = parent;\r
+       evas_object_geometry_get(parent, &x, &y, &w, &h);\r
+       wd->object = obj;\r
+       wd->x = x;\r
+       wd->y = y;\r
+       wd->w = w;\r
+       wd->h = h;\r
+       wd->num = 0;\r
+       wd->edit_disable = EINA_FALSE;\r
+       wd->cur_first_slot = 1;\r
+       //wd->view_slot_num = BASIC_SLOT_NUMBER;\r
+       wd->view_slot_num = 3;\r
+\r
+       // initialization\r
+       // edit box\r
+       wd->ebx = edje_object_add(wd->evas);\r
+       if(wd->ebx == NULL)\r
+               return NULL;\r
+       _elm_theme_object_set(obj, wd->ebx, "tab", "dim", "default");\r
+       evas_object_resize(wd->ebx, wd->w, wd->h);\r
+       evas_object_move(wd->ebx, wd->x, wd->y);\r
+       evas_object_hide(wd->ebx);\r
+       evas_object_event_callback_add(wd->ebx, EVAS_CALLBACK_MOUSE_UP, edit_up_cb, wd);\r
+\r
+       // initialization\r
+       /* load background edj */\r
+       wd->edje = edje_object_add(wd->evas);\r
+       snprintf(buf, sizeof(buf), "bg_portrait_%d", wd->view_slot_num);\r
+       _elm_theme_object_set(obj, wd->edje, "tab", buf, "default");\r
+       if(wd->edje == NULL) {\r
+               printf("Cannot load bg edj\n");\r
+               return NULL;\r
+       }\r
+       // initialization\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_MOUSE_DOWN,  press_down_cb, wd);\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_MOUSE_UP,  press_up_cb, wd);\r
+       evas_object_show(wd->edje);\r
+\r
+       // initialization\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_RESIZE, _tab_object_resize, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _tab_object_move, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _tab_object_show, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _tab_object_hide, obj);\r
+\r
+       // initialization\r
+       //FIXME\r
+       //      evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);\r
+\r
+       evas_object_smart_member_add(wd->ebx, obj);\r
+       elm_widget_resize_object_set(obj, wd->edje);\r
+\r
+       // initialization\r
+       _sizing_eval(obj);\r
+\r
+       return obj;\r
+}\r
+\r
+\r
+/**\r
+ * Set the mode of tab object\r
+ *\r
+ * @param obj The tab object\r
+ * @param mode The mode of tab\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_set(Evas_Object *obj, int mode)\r
+{\r
+       int i = 1;\r
+       char buf[MAX_ARGS];\r
+       Widget_Data *wd;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(obj == NULL) {\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return;\r
+       }\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL) {\r
+               printf("Cannot get smart data\n");\r
+               return;\r
+       }\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               edje_object_part_unswallow(wd->edje, item->base);\r
+       }\r
+\r
+       evas_object_del(wd->edje);\r
+\r
+       evas_object_smart_member_del(wd->ebx);\r
+//     elm_widget_resize_object_set(obj, wd->edje);\r
+\r
+       // load edj\r
+       if(mode >= ELM_TAB_PORTRAIT_2 && mode <= ELM_TAB_PORTRAIT_4){\r
+               snprintf(buf, sizeof(buf), "bg_portrait_%d", mode);\r
+       }else if(mode >= ELM_TAB_LANDSCAPE_2 && mode <= ELM_TAB_LANDSCAPE_5){\r
+               snprintf(buf, sizeof(buf), "bg_landscape_%d", mode - LANDSCAPE_GAP);\r
+       }\r
+       wd->edje = edje_object_add(wd->evas);\r
+       if(wd->edje == NULL) {\r
+               printf("Cannot load bg edj\n");\r
+               return;\r
+       }\r
+\r
+       _elm_theme_object_set(obj, wd->edje, "tab", buf, elm_widget_style_get(obj));\r
+\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_MOUSE_DOWN,  press_down_cb, wd);\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_MOUSE_UP,  press_up_cb, wd);\r
+       evas_object_show(wd->edje);\r
+\r
+       evas_object_smart_member_add(wd->ebx, obj);\r
+       elm_widget_resize_object_set(obj, wd->edje);\r
+\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_RESIZE, _tab_object_resize, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _tab_object_move, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _tab_object_show, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _tab_object_hide, obj);\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               snprintf(buf, sizeof(buf), "slot_%d", item->slot);\r
+               edje_object_part_swallow(wd->edje, buf, item->base);\r
+               i++;\r
+       }\r
+\r
+       // set current mode\r
+       if(mode < 10) wd->mode = PORTRAIT;\r
+       else wd->mode = LANDSCAPE;\r
+\r
+       wd->view_slot_num = mode % LANDSCAPE_GAP;\r
+\r
+       light_check(wd);\r
+\r
+       evas_object_resize(wd->edje, wd->w, wd->h);\r
+}\r
+\r
+/**\r
+ * Add new item\r
+ *\r
+ * @param obj The tab object\r
+ * @param      icon The icon of item\r
+ * @param      label The label of item\r
+ * @param      func Callback function of item\r
+ * @param      data The data of callback function\r
+ * @return The item of tab\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data)\r
+{\r
+       char buf[MAX_ARGS];\r
+       Elm_Tab_Item *it;\r
+       Widget_Data *wd;\r
+\r
+       if(obj == NULL) {\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return NULL;\r
+       }\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL) {\r
+               printf("Cannot get smart data\n");\r
+               return NULL;\r
+       }\r
+\r
+       it = ELM_NEW(Elm_Tab_Item);\r
+       if(it == NULL) {\r
+               printf("Cannot add item");\r
+               return NULL;\r
+       }\r
+       wd->items = eina_list_append(wd->items, it);\r
+       it->obj = obj;\r
+       it->label = eina_stringshare_add(label);\r
+       it->icon = icon;\r
+       it->badge = 0;\r
+       it->func = func;\r
+       it->data = data;\r
+       it->base = edje_object_add(evas_object_evas_get(obj));\r
+       if(it->base == NULL) {\r
+               printf("Cannot load bg edj\n");\r
+               return NULL;\r
+       }\r
+       _elm_theme_object_set(obj, it->base, "tab", "item", elm_widget_style_get(obj));\r
+       elm_widget_sub_object_add(obj, it->base);\r
+\r
+       edje_object_signal_callback_add(it->base, "elm,action,click", "elm", tab_item_cb, (void *)it);\r
+\r
+       if (it->label){\r
+               edje_object_part_text_set(it->base, "elm.text", it->label);\r
+       }\r
+\r
+       if (it->icon){\r
+               //              int ms = 0;\r
+\r
+               //              ms = ((double)wd->icon_size * _elm_config->scale);\r
+               evas_object_size_hint_min_set(it->icon, 24, 24);\r
+               evas_object_size_hint_max_set(it->icon, 40, 40);\r
+               edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon);\r
+               evas_object_show(it->icon);\r
+               elm_widget_sub_object_add(obj, it->icon);\r
+       }\r
+\r
+       if (it->label && it->icon){\r
+               edje_object_signal_emit(it->base, "elm,state,icon_text", "elm");\r
+       }\r
+\r
+       wd->num += 1;\r
+       it->slot = wd->num;\r
+       snprintf(buf, sizeof(buf), "slot_%d", wd->num);\r
+       edje_object_part_swallow(wd->edje, buf, it->base);\r
+\r
+       light_check(wd);\r
+\r
+       return it;\r
+}\r
+\r
+/**\r
+ * Delete item from tab by index\r
+ *\r
+ * @param      it The item of tab\r
+\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_item_del(Elm_Tab_Item *it)\r
+{\r
+       int check = 0;\r
+       int i = 1;\r
+       char buf[MAX_ARGS];\r
+       Widget_Data *wd;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(it->obj == NULL) {\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return;\r
+       }\r
+       wd = elm_widget_data_get(it->obj);\r
+       if(wd == NULL) {\r
+               printf("Cannot get smart data\n");\r
+               return;\r
+       }\r
+\r
+       edje_object_part_unswallow(wd->edje, it->base);\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(check){\r
+                       edje_object_part_unswallow(wd->edje, item->base);\r
+                       snprintf(buf, sizeof(buf), "slot_%d", i-1);\r
+                       edje_object_part_swallow(wd->edje, buf, item->base);\r
+               }\r
+               if(it == item){\r
+                       check = 1;\r
+               }\r
+               i++;\r
+       }\r
+\r
+       eina_stringshare_del(it->label);\r
+       if (it->icon) evas_object_del(it->icon);\r
+       evas_object_del(it->base);\r
+       wd->items = eina_list_remove(wd->items, it);\r
+       wd->num = wd->num - 1;\r
+}\r
+\r
+/**\r
+ * Select item in tab\r
+ *\r
+ * @param      it The item of tab\r
+\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_item_select(Elm_Tab_Item *it)\r
+{\r
+       _selected_box(it);\r
+}\r
+\r
+/**\r
+ * Get the icon of item\r
+ *\r
+ * @param      it The item of tab\r
+ * @return The icon object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Evas_Object *elm_tab_item_icon_get(Elm_Tab_Item *it)\r
+{\r
+       return it->icon;\r
+}\r
+\r
+/**\r
+ * Get the label of item\r
+ *\r
+ * @param      it The item of tab\r
+ * @return the label of item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI const char *elm_tab_item_label_get(Elm_Tab_Item *it)\r
+{\r
+       return it->label;\r
+}\r
+\r
+/**\r
+ * Set the label of item\r
+ *\r
+ * @param      it The item of tab\r
+ * @param      label The label of item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_item_label_set(Elm_Tab_Item *it, const char *label)\r
+{\r
+       if(!it->base) return;\r
+\r
+       edje_object_part_text_set(it->base, "elm.text", label);\r
+}\r
+\r
+/**\r
+ * Set the badge of item.\r
+ *\r
+ * @param      it The item of tab\r
+ * @param      badge The number in item badge. If -1, badge is not visible. Otherwise, it is just number.\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_item_badge_set(Elm_Tab_Item *it, const int badge)\r
+{\r
+       char buf[MAX_ARGS];\r
+\r
+       if(!it->base) return;\r
+\r
+       if(it->badge == badge) return;\r
+\r
+       if(badge < -1) {\r
+               printf("elm_tab_item_badge_set : second parameter range not availble. (-1 <= badge < 1000)\n");\r
+               return;\r
+       }\r
+\r
+       it->badge = badge;\r
+\r
+       if(badge == -1){\r
+               edje_object_signal_emit(it->base, "elm,badge,unvisible", "elm");\r
+       }else{\r
+               if(it->badge > 1000) {\r
+                       printf("Badge Number is too large. ( badge < 1000)\n");\r
+                       return;\r
+               }\r
+\r
+               snprintf(buf, sizeof(buf), "%d", it->badge);\r
+               edje_object_part_text_set(it->base, "elm.text.badge", buf);\r
+\r
+               if(it->badge > 100){\r
+                       edje_object_signal_emit(it->base, "elm,badge,text_normal", "elm");\r
+               }else{\r
+                       edje_object_signal_emit(it->base, "elm,badge,text_small", "elm");\r
+               }\r
+               edje_object_signal_emit(it->base, "elm,badge,visible", "elm");\r
+       }\r
+}\r
+\r
+/**\r
+ * Get the selected item.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_selected_item_get(Evas_Object *obj)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->selected) return item;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+/**\r
+ * Get the first item.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_first_item_get(Evas_Object *obj)\r
+{\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       return eina_list_data_get(wd->items);\r
+}\r
+\r
+/**\r
+ * Get the last item.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_last_item_get(Evas_Object *obj)\r
+{\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       return eina_list_data_get(eina_list_last(wd->items));\r
+}\r
+\r
+/**\r
+ * Get the items.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Eina_List *elm_tab_items_get(Evas_Object *obj)\r
+{\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       return wd->items;\r
+}\r
+\r
+/**\r
+ * Get the previous item.\r
+ *\r
+ * @param      it The item of tab\r
+ * @return     The previous item of the parameter item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_item_prev(Elm_Tab_Item *it)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(it->obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(it == item){\r
+                       l = eina_list_prev(l);\r
+                       if(!l) return NULL;\r
+                       return eina_list_data_get(l);\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+/**\r
+ * Get the next item.\r
+ *\r
+ * @param      obj The tab object\r
+ * @return     The next item of the parameter item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_item_next(Elm_Tab_Item *it)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(it->obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(it == item){\r
+                       l = eina_list_next(l);\r
+                       if(!l) return NULL;\r
+                       return eina_list_data_get(l);\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+/**\r
+ * Move the tab object\r
+ *\r
+ * @param      obj The tab object\r
+ * @param      direction the direction of movement\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_move(Evas_Object *obj, int direction)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       if(obj == NULL) {\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return;\r
+       }\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL) {\r
+               printf("Cannot get smart data\n");\r
+               return;\r
+       }\r
+\r
+       if(direction == ELM_TAB_MOVE_LEFT){\r
+               _move_obj_to_left(wd);\r
+       }else if(direction == ELM_TAB_MOVE_RIGHT){\r
+               _move_obj_to_right(wd);\r
+       }\r
+}\r
+\r
+/**\r
+ * Set the edit mode of the tab disable\r
+ *\r
+ * @param      obj The tab object\r
+ * @param      disable if 1, edit mode is disable.\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_edit_disable_set(Evas_Object *obj, Eina_Bool disable)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       if(obj == NULL) {\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return;\r
+       }\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL) {\r
+               printf("Cannot get smart data\n");\r
+               return;\r
+       }\r
+\r
+       wd->edit_disable = disable;\r
+}\r
+\r
+/**\r
+ * Get the availability for the edit mode of the tab\r
+ *\r
+ * @param      obj The tab object\r
+ * @return  disable or not\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Eina_Bool elm_tab_edit_disable_get(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       if(obj == NULL) {\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return -1;\r
+       }\r
+\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL) {\r
+               printf("Cannot get smart data\n");\r
+               return -1;\r
+       }\r
+\r
+       return wd->edit_disable;\r
+}\r
+\r
+\r
+\r
+///////////////////////////////////////////////////////////////////\r
+//\r
+//  basic utility function\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+\r
+static void light_check(Widget_Data *wd)\r
+{\r
+       edje_object_signal_emit(wd->edje, "off_light", "light");\r
+\r
+       if(wd->view_slot_num > wd->num) return;\r
+\r
+       if(wd->cur_first_slot > 1){\r
+               edje_object_signal_emit(wd->edje, "left", "light");\r
+       }\r
+       if(wd->cur_first_slot + wd->view_slot_num - 1 != wd->num){\r
+               edje_object_signal_emit(wd->edje, "right", "light");\r
+       }\r
+}\r
+\r
+static void select_check(Widget_Data *wd)\r
+{\r
+       int i = 1;\r
+//     int selected = -1;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(wd->cur_first_slot <= i && wd->cur_first_slot + wd->view_slot_num > i){\r
+                       if(item->selected){\r
+                               edje_object_signal_emit(item->base, "selected", "elm");\r
+                       \r
+                       }\r
+//                             selected = i;\r
+//                     }else{\r
+//                             snprintf(buf, sizeof(buf), "show_partition_%d_%d", i, i+1);\r
+//                             edje_object_signal_emit(wd->edje, buf, "elm");\r
+//                     }\r
+               }else{\r
+                       edje_object_signal_emit(item->base, "unselected", "elm");\r
+               }\r
+               i++;\r
+       }\r
+\r
+//     snprintf(buf, sizeof(buf), "hide_partition_%d_%d", selected, selected+1);\r
+//     edje_object_signal_emit(wd->edje, buf, "elm");\r
+//     snprintf(buf, sizeof(buf), "hide_partition_%d_%d", selected-1, selected);\r
+//     edje_object_signal_emit(wd->edje, buf, "elm");\r
+}\r
+\r
+static int _selected_box(Elm_Tab_Item *it)\r
+{\r
+       int i = 1;\r
+       int check = 0;\r
+       Evas_Object *icon;\r
+       char buf[MAX_ARGS];\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               edje_object_signal_emit(item->base, "unselected", "elm");\r
+               item->selected = EINA_FALSE;\r
+\r
+               icon = edje_object_part_swallow_get(item->base, "elm.swallow.icon");\r
+               if(icon){\r
+                       if(strcmp(evas_object_type_get(icon), "edje") == 0){\r
+                               edje_object_signal_emit(icon, "elm,state,unselected", "elm");\r
+                       }else{\r
+                               if(_EDJ(icon))\r
+                                       edje_object_signal_emit(_EDJ(icon), "elm,state,unselected", "elm");\r
+                       }\r
+               }\r
+\r
+               if(it == item){\r
+                       edje_object_signal_emit(it->base, "selected", "elm");\r
+                       snprintf(buf, sizeof(buf), "selected_%d", i);\r
+                       edje_object_signal_emit(wd->edje, buf, "elm");\r
+\r
+                       if(icon){\r
+                               if(strcmp(evas_object_type_get(icon), "edje") == 0){\r
+                                       edje_object_signal_emit(icon, "elm,state,selected", "elm");\r
+                               }else{\r
+                                       if(_EDJ(icon))\r
+                                               edje_object_signal_emit(_EDJ(icon), "elm,state,selected", "elm");\r
+                               }\r
+                       }\r
+                       item->selected = EINA_TRUE;\r
+\r
+                       check = 1;\r
+               }\r
+               i++;\r
+       }\r
+\r
+       if(!check) return EXIT_FAILURE;\r
+\r
+       if (it->func) it->func((void *)(it->data), it->obj, it);\r
+       evas_object_smart_callback_call(it->obj, "clicked", it);\r
+\r
+//     select_check(wd);\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////\r
+//\r
+//  general function\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+\r
+static int _move_obj_to_left(Widget_Data *wd)\r
+{\r
+       char buf[MAX_ARGS];\r
+       int first_slot;\r
+\r
+       first_slot = wd->cur_first_slot + wd->view_slot_num;\r
+       if(first_slot + wd->view_slot_num > wd->num){\r
+               first_slot = wd->num - wd->view_slot_num +1;\r
+       }\r
+\r
+       snprintf(buf, sizeof(buf), "step_%d", first_slot);\r
+       edje_object_signal_emit(wd->edje, buf, "elm");\r
+       wd->cur_first_slot = first_slot;\r
+\r
+       select_check(wd);\r
+\r
+       light_check(wd);\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static int _move_obj_to_right(Widget_Data *wd)\r
+{\r
+       char buf[MAX_ARGS];\r
+       int first_slot;\r
+\r
+       first_slot = wd->cur_first_slot - wd->view_slot_num;\r
+       if(first_slot < 1){\r
+               first_slot = 1;\r
+       }\r
+\r
+       snprintf(buf, sizeof(buf), "step_%d", first_slot);\r
+       edje_object_signal_emit(wd->edje, buf, "elm");\r
+       wd->cur_first_slot = first_slot;\r
+\r
+       select_check(wd);\r
+\r
+       light_check(wd);\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static void edit_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)\r
+{\r
+       char buf[MAX_ARGS];\r
+       Evas_Object *icon;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->selected){\r
+                       edje_object_signal_emit(item->base, "selected", "elm");\r
+                       icon = edje_object_part_swallow_get(item->base, "elm.swallow.icon");\r
+                       if(icon){\r
+                               if(strcmp(evas_object_type_get(icon), "edje") == 0){\r
+                                       edje_object_signal_emit(icon, "elm,state,selected", "elm");\r
+                               }else{\r
+                                       if(_EDJ(icon))\r
+                                               edje_object_signal_emit(_EDJ(icon), "elm,state,selected", "elm");\r
+                               }\r
+                       }\r
+               }\r
+               edje_object_signal_callback_add(item->base, "elm,action,click", "elm", tab_item_cb, item);\r
+               evas_object_event_callback_del(item->base, EVAS_CALLBACK_MOUSE_DOWN,  item_down_cb);\r
+       }\r
+\r
+       evas_object_event_callback_del(wd->edje, EVAS_CALLBACK_MOUSE_DOWN,  press_down_cb);\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_MOUSE_DOWN,  press_down_cb, wd);\r
+       evas_object_event_callback_del(wd->edje, EVAS_CALLBACK_MOUSE_UP,  press_up_cb);\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_MOUSE_UP,  press_up_cb, wd);\r
+\r
+       snprintf(buf, sizeof(buf), "step_%d", wd->cur_first_slot);\r
+       edje_object_signal_emit(wd->edje, buf, "elm");\r
+\r
+       light_check(wd);\r
+       evas_object_hide(wd->ebx);\r
+}\r
+\r
+static Eina_Bool item_move_cb(void *data, int type, void *event_info)\r
+{\r
+       Evas_Object *obj;\r
+       Ecore_Event_Mouse_Move *ev = event_info;\r
+       Evas_Coord x, y, w, h, mx, my, mw, mh, ex, ey;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       obj = wd->moving_obj;\r
+\r
+       evas_object_geometry_get(obj, NULL, NULL ,&w, &h);\r
+       evas_object_geometry_get(wd->edje, &ex, &ey , NULL, NULL);\r
+       edje_object_part_geometry_get(wd->edje, "bg_b", &mx, &my ,&mw, &mh);\r
+\r
+       if(ev->x < ex + mx + w/2) x = ex + mx;\r
+       else if(ev->x > ex + mx + mw - w/2) x = ex + mx + mw - w;\r
+       else x = ev->x - w/2;\r
+\r
+       if(ev->y < ey + my + h) y = ey + my;\r
+       else if(ev->y > ey + my + mh) y = ey + my + mh - h;\r
+       else y = ev->y - h;\r
+\r
+       evas_object_move(obj, x, y);\r
+\r
+       return 1;\r
+}\r
+\r
+static int sort_cb(const void *d1, const void *d2)\r
+{\r
+       Elm_Tab_Item *item1, *item2;\r
+\r
+       item1 = (Elm_Tab_Item *)d1;\r
+       item2 = (Elm_Tab_Item *)d2;\r
+\r
+       return item1->slot > item2->slot ? 1 : -1;\r
+}\r
+\r
+static Eina_Bool item_up_cb(void *data, int type, void *event_info)\r
+{\r
+       Evas_Object *obj;\r
+       Ecore_Event_Mouse_Button *ev = event_info;\r
+       char buf[MAX_ARGS];\r
+       Evas_Coord x, y, w, h;\r
+       int i = 0;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Elm_Tab_Item *edit_to_item, *edit_from_item;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       obj = wd->moving_obj;\r
+\r
+       wd->edit_to = 0;\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               i++;\r
+               if(item->base == obj) continue;\r
+               evas_object_geometry_get(item->base, &x, &y, &w, &h);\r
+               if(x < ev->x && ev->x < x+w && y < ev->y && ev->y < y+h){\r
+                       wd->edit_to = i;\r
+               }\r
+       }\r
+\r
+       if(wd->edit_to > 0 && wd->edit_to <= wd->num){\r
+\r
+               edit_to_item = eina_list_nth(wd->items, wd->edit_to-1);\r
+               edit_from_item = eina_list_nth(wd->items, wd->edit_from-1);\r
+\r
+               edje_object_part_unswallow(wd->edje, edit_to_item->base);\r
+               snprintf(buf, sizeof(buf), "slot_%d", wd->edit_from);\r
+               edje_object_part_swallow(wd->edje, buf, edit_to_item->base);\r
+               edit_to_item->slot = wd->edit_from;\r
+\r
+               snprintf(buf, sizeof(buf), "slot_%d", wd->edit_to);\r
+               edje_object_part_swallow(wd->edje, buf, edit_from_item->base);\r
+               edit_from_item->slot = wd->edit_to;\r
+\r
+               wd->items = eina_list_sort(wd->items, eina_list_count(wd->items), sort_cb);\r
+\r
+       }else{\r
+               wd->edit_to = wd->edit_from;\r
+               snprintf(buf, sizeof(buf), "slot_%d", wd->edit_from);\r
+               edje_object_part_swallow(wd->edje, buf, obj);\r
+       }\r
+\r
+       ecore_event_handler_del(wd->move_event);\r
+       wd->move_event = NULL;\r
+       ecore_event_handler_del(wd->up_event);\r
+       wd->up_event = NULL;\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static void item_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)\r
+{\r
+       Evas_Event_Mouse_Down *ev = event_info;\r
+       Evas_Coord x, y, w, h;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       wd->moving_obj = obj;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->base == obj) wd->edit_from = item->slot;\r
+       }\r
+\r
+       edje_object_part_unswallow(wd->edje, obj);\r
+       evas_object_geometry_get(obj, &x, &y, &w, &h);\r
+       evas_object_move(obj, ev->output.x - w/2 , ev->output.y - h);\r
+       edje_object_signal_emit(obj, "edit", "elm");\r
+\r
+       wd->up_event = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, item_up_cb, (void *)wd);\r
+       wd->move_event = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, item_move_cb, (void *)wd);\r
+}\r
+\r
+static void edit_mode(void *data)\r
+{\r
+       Evas_Object *icon;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       edje_object_signal_emit(wd->edje, "edit", "elm");\r
+\r
+       if((int)(wd->num/wd->view_slot_num) < 2){\r
+               edje_object_signal_emit(wd->edje, "edit_2", "elm");\r
+       }else{\r
+               edje_object_signal_emit(wd->edje, "edit_3", "elm");\r
+       }\r
+\r
+       // delete normal mode callback & add normal mode callback\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               edje_object_signal_emit(item->base, "unselected", "elm");\r
+               icon = edje_object_part_swallow_get(item->base, "elm.swallow.icon");\r
+               if(icon){\r
+                       if(strcmp(evas_object_type_get(icon), "edje") == 0){\r
+                               edje_object_signal_emit(icon, "elm,state,unselected", "elm");\r
+                       }else{\r
+                               if(_EDJ(icon))\r
+                                       edje_object_signal_emit(_EDJ(icon), "elm,state,unselected", "elm");\r
+                       }\r
+               }\r
+               edje_object_signal_callback_del(item->base, "elm,action,click", "elm", tab_item_cb);\r
+               evas_object_event_callback_add(item->base, EVAS_CALLBACK_MOUSE_DOWN, item_down_cb, wd);\r
+       }\r
+       evas_object_event_callback_del(wd->edje, EVAS_CALLBACK_MOUSE_DOWN,  press_down_cb);\r
+       evas_object_event_callback_del(wd->edje, EVAS_CALLBACK_MOUSE_UP,  press_up_cb);\r
+       evas_object_show(wd->ebx);\r
+\r
+       edje_object_signal_emit(wd->edje, "off_light", "light");\r
+}\r
+\r
+\r
+static Eina_Bool tab_timer_cb(void* data)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       if(wd->time > KEYDOWN_INTERVAL){\r
+               evas_object_event_callback_del(wd->edje, EVAS_CALLBACK_MOUSE_MOVE,  press_move_cb);\r
+\r
+               if(!wd->edit_disable) edit_mode(wd);\r
+\r
+               if(wd->timer){\r
+                       ecore_timer_del(wd->timer);\r
+                       wd->timer = NULL;\r
+               }\r
+\r
+       } else {\r
+               wd->time += 0.1;\r
+       }\r
+\r
+       return EXIT_FAILURE;\r
+}\r
+\r
+static void press_move_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)\r
+{\r
+       Evas_Event_Mouse_Down *ev = event_info;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       if(abs(wd->tab_down_x-ev->output.x) > 10 || abs(wd->tab_down_y-ev->output.y) > 10){\r
+               if(wd->timer){\r
+                       ecore_timer_del(wd->timer);\r
+                       wd->timer = NULL;\r
+               }\r
+       }\r
+}\r
+\r
+static void press_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)\r
+{\r
+       Evas_Event_Mouse_Down *ev = event_info;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       wd->flag = EINA_TRUE;\r
+       wd->tab_down_x = ev->output.x;\r
+       wd->tab_down_y = ev->output.y;\r
+\r
+       wd->time = 0;\r
+       wd->timer = ecore_timer_add(0.1, tab_timer_cb, wd);\r
+\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_MOUSE_MOVE,  press_move_cb, wd);\r
+}\r
+\r
+static void press_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)\r
+{\r
+       Evas_Event_Mouse_Up *ev = event_info;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       Evas_Coord x, y, w, h;\r
+\r
+       evas_object_event_callback_del(wd->edje, EVAS_CALLBACK_MOUSE_MOVE,  press_move_cb);\r
+\r
+       if(wd->time < KEYDOWN_INTERVAL){\r
+               if(wd->timer){\r
+                       ecore_timer_del(wd->timer);\r
+                       wd->timer = NULL;\r
+               }\r
+       } else {\r
+               return;\r
+       }\r
+\r
+       evas_object_geometry_get(wd->edje, &x, &y, &w, &h);\r
+\r
+       if(ev->output.y > y+(h*1.5) && abs(ev->output.x - wd->tab_down_x) < wd->w/10){\r
+               if(!wd->edit_disable) edit_mode(wd);\r
+       }else{\r
+               // return if dont need to move\r
+               if(wd->num <= wd->view_slot_num) return;\r
+\r
+               if(wd->flag == EINA_TRUE){\r
+                       if(abs(wd->tab_down_y - ev->output.y) < wd->h){\r
+                               if((wd->tab_down_x - ev->output.x ) > wd->w / 4){\r
+                                       _move_obj_to_left(wd);\r
+                               }else if((ev->output.x - wd->tab_down_x) > wd->w / 4){\r
+                                       _move_obj_to_right(wd);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       wd->flag = EINA_FALSE;\r
+}\r
+\r
+void tab_item_cb(void *data, Evas_Object *obj, const char *emission, const char *source)\r
+{\r
+       Elm_Tab_Item *it = (Elm_Tab_Item *)data;\r
+       if(it->obj == NULL)\r
+               return;\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       if(wd == NULL)\r
+               return;\r
+\r
+       if(wd->time > KEYDOWN_INTERVAL) return;\r
+       _selected_box(it);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////\r
+//\r
+//  Smart Object basic function\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+\r
+static void _tab_object_move(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+       Evas_Coord x, y;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       evas_object_geometry_get(wd->edje, &x, &y, NULL, NULL);\r
+\r
+       wd->x = x;\r
+       wd->y = y;\r
+\r
+       evas_object_move(wd->edje, x, y);\r
+}\r
+\r
+\r
+static void _tab_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+       Evas_Coord w, h;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       evas_object_geometry_get(wd->edje, NULL, NULL, &w, &h);\r
+\r
+       wd->w = w;\r
+       wd->h = h;\r
+\r
+       evas_object_resize(wd->edje, w, h);\r
+\r
+       evas_object_geometry_get(wd->parent, NULL, NULL, &w, &h);\r
+       evas_object_resize(wd->ebx, w, h);\r
+}\r
+\r
+\r
+static void _tab_object_show(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       edit_up_cb(wd, NULL, NULL, NULL);\r
+\r
+       evas_object_show(wd->edje);\r
+}\r
+\r
+\r
+\r
+static void _tab_object_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+    DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       evas_object_hide(wd->edje);\r
+       evas_object_hide(wd->ebx);\r
+}\r
+\r
diff --git a/src/lib/elm_tabbar.c b/src/lib/elm_tabbar.c
new file mode 100644 (file)
index 0000000..1bf31d9
--- /dev/null
@@ -0,0 +1,1601 @@
+/*\r
+ * SLP\r
+ * Copyright (c) 2009 Samsung Electronics, Inc.\r
+ * All rights reserved.\r
+ *\r
+ * This software is a confidential and proprietary information\r
+ * of Samsung Electronics, Inc. ("Confidential Information").  You\r
+ * shall not disclose such Confidential Information and shall use\r
+ * it only in accordance with the terms of the license agreement\r
+ * you entered into with Samsung Electronics.\r
+ */\r
+\r
+\r
+/**\r
+ * @defgroup Tab Tab\r
+ * @ingroup Elementary\r
+ *\r
+ * This is a Tab. It can contain label and icon objects.\r
+ * You can change the location of items.\r
+ */\r
+\r
+\r
+#include <string.h>\r
+#include <math.h>\r
+\r
+#include <Elementary.h>\r
+#include "elm_priv.h"\r
+\r
+#ifndef EAPI\r
+#define EAPI __attribute__ ((visibility("default")))\r
+#endif\r
+\r
+#define MAX_ARGS       512\r
+\r
+#define ELM_MAX(v1, v2)    (((v1) > (v2)) ? (v1) : (v2))\r
+#define _EDJ(x) (Evas_Object *)elm_layout_edje_get(x)\r
+\r
+#define AQUA_THEME_FILE "/usr/share/elementary/themes/aqua.edj"\r
+       \r
+Evas_Object *btn;\r
+\r
+// internal data structure of tab object\r
+typedef struct _Widget_Data Widget_Data;\r
+\r
+struct _Widget_Data\r
+{\r
+       Evas *evas;\r
+       Evas_Object *object;\r
+       Evas_Object *parent;\r
+       Evas_Object *view;\r
+       Evas_Object *edit_box;\r
+       Evas_Object *edit_table;\r
+       Evas_Object *navigation;\r
+       Evas_Object *edje;\r
+       Evas_Object *box;\r
+       Evas_Object *rect;\r
+       Evas_Object *moving_obj;\r
+       Elm_Tab_Item *moving_item;\r
+\r
+       Evas_Coord x, y, w, h;\r
+\r
+       Eina_Bool edit_mode;\r
+\r
+       int empty_num;\r
+       int num;\r
+\r
+       Eina_List *items;\r
+\r
+       int animating;\r
+\r
+       Ecore_Event_Handler *move_event;\r
+       Ecore_Event_Handler *up_event;\r
+       Ecore_Event_Handler *bar_move_event;\r
+       Ecore_Event_Handler *bar_up_event;\r
+};\r
+\r
+struct _Elm_Tab_Item\r
+  {\r
+       Evas_Object *obj;\r
+       Evas_Object *base;\r
+       Evas_Object *edit_item;\r
+       Evas_Object *view;\r
+       Evas_Object *icon;\r
+       const char *icon_path;\r
+       const char *label;\r
+       int order;\r
+       int badge;\r
+       Eina_Bool selected : 1;\r
+       Eina_Bool editable : 1;\r
+       Eina_Bool in_bar : 1;\r
+  };\r
+\r
+typedef struct _Animation_Data Animation_Data;\r
+\r
+struct _Animation_Data\r
+  {\r
+       Evas_Object *obj;\r
+       Evas_Coord fx;\r
+       Evas_Coord fy;\r
+       Evas_Coord fw;\r
+       Evas_Coord fh;\r
+       Evas_Coord tx;\r
+       Evas_Coord ty;\r
+       Evas_Coord tw;\r
+       Evas_Coord th;\r
+       unsigned int start_time;\r
+       double time;\r
+       void (*func)(void *data, Evas_Object *obj);\r
+       void *data;\r
+       Ecore_Animator *timer;\r
+  };\r
+\r
+///////////////////////////////////////////////////////////////////\r
+//\r
+//  Smart Object basic function\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+\r
+static void _tab_object_move(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+       Evas_Coord x, y;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       evas_object_geometry_get(wd->edje, &x, &y, NULL, NULL);\r
+\r
+       wd->x = x;\r
+       wd->y = y;\r
+\r
+       evas_object_move(wd->edje, x, y);\r
+//     evas_object_move(wd->box, x, y);\r
+       evas_object_move(wd->view, x, y);\r
+       \r
+       evas_object_geometry_get(wd->parent, &x, &y, NULL, NULL);\r
+       evas_object_move(wd->edit_box, x, y);\r
+}\r
+\r
+\r
+static void _tab_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+    Evas_Coord y, y_, w, h, height;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       evas_object_geometry_get(wd->edje, NULL, &y, &w, &h);\r
+\r
+       wd->w = w;\r
+       wd->h = h;\r
+\r
+       evas_object_resize(wd->edje, w, h);\r
+\r
+       evas_object_geometry_get(edje_object_part_object_get(wd->edje, "bg_image"), NULL, NULL, NULL, &height);\r
+       evas_object_resize(wd->view, w, h - height + 1);\r
+       evas_object_geometry_get(wd->parent, NULL, &y_, NULL, NULL);\r
+       evas_object_resize(wd->edit_box, w, h + y - y_);\r
+}\r
+\r
+\r
+static void _tab_object_show(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+       DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       evas_object_show(wd->view);\r
+       evas_object_show(wd->edit_box);\r
+       evas_object_show(wd->edje);\r
+//     evas_object_show(wd->box);\r
+}\r
+\r
+\r
+\r
+static void _tab_object_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)\r
+{\r
+    DBG("%s", __func__);\r
+\r
+       Widget_Data *wd;\r
+\r
+       if(!data) return;\r
+       wd = elm_widget_data_get((Evas_Object *)data);\r
+       if(!wd) return;\r
+\r
+       evas_object_hide(wd->view);\r
+       evas_object_hide(wd->edit_box);\r
+       evas_object_hide(wd->edje);\r
+//     evas_object_hide(wd->box);\r
+}\r
+\r
+static void\r
+_del_hook(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       Elm_Tab_Item *item;\r
+\r
+       if (!wd) return;\r
+\r
+       if (wd->view) {\r
+               evas_object_smart_member_del(wd->view);\r
+               evas_object_del(wd->view);\r
+               wd->view = NULL;\r
+       }\r
+\r
+       if (wd->edit_box) {\r
+               evas_object_smart_member_del(wd->edit_box);\r
+               evas_object_del(wd->edit_box);\r
+               wd->edit_box = NULL;\r
+       }\r
+\r
+       if (wd->navigation) {\r
+               evas_object_smart_member_del(wd->navigation);\r
+               evas_object_del(wd->navigation);\r
+               wd->navigation = NULL;\r
+       }\r
+\r
+       if (wd->edje) {\r
+               evas_object_smart_member_del(wd->edje);\r
+               evas_object_del(wd->edje);\r
+               wd->edje = NULL;\r
+       }\r
+\r
+       if (wd->box) {\r
+               evas_object_smart_member_del(wd->box);\r
+               evas_object_del(wd->box);\r
+               wd->box = NULL;\r
+       }\r
+\r
+       EINA_LIST_FREE(wd->items, item){\r
+               eina_stringshare_del(item->label);\r
+               if (item->icon) evas_object_del(item->icon);\r
+               if(item->base) evas_object_del(item->base);\r
+               if(item->edit_item) evas_object_del(item->edit_item);\r
+               free(item);\r
+       }\r
+\r
+       free(wd);\r
+}\r
+\r
+static void\r
+_theme_hook(Evas_Object *obj)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       char buf[MAX_ARGS];\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       _elm_theme_object_set(obj, wd->edje, "tab", buf, elm_widget_style_get(obj));\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               _elm_theme_object_set(obj, item->base, "tab", "item", elm_widget_style_get(item->obj));\r
+               if (item->label){\r
+                       edje_object_part_text_set(item->base, "elm.text", item->label);\r
+               }\r
+\r
+               if (item->icon){\r
+       //              int ms = 0;\r
+\r
+       //              ms = ((double)wd->icon_size * _elm_config->scale);\r
+                       evas_object_size_hint_min_set(item->icon, 40, 40);\r
+                       evas_object_size_hint_max_set(item->icon, 100, 100);\r
+                       edje_object_part_swallow(item->base, "elm.swallow.icon", item->icon);\r
+                       evas_object_show(item->icon);\r
+                       elm_widget_sub_object_add(obj, item->icon);\r
+               }\r
+       }\r
+}\r
+\r
+static void\r
+_sub_del(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       //Evas_Object *sub = event_info;\r
+       if (!wd) return;\r
+       /*\r
+          if (sub == wd->icon)\r
+          {\r
+          edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");\r
+          evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,\r
+          _changed_size_hints, obj);\r
+          wd->icon = NULL;\r
+          edje_object_message_signal_process(wd->btn);\r
+          _sizing_eval(obj);\r
+          }\r
+          */\r
+}\r
+\r
+\r
+static void\r
+_sizing_eval(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+\r
+       if (!wd) return;\r
+\r
+       DBG("[%s]\n", __func__);\r
+\r
+       _tab_object_move(obj, NULL, obj, NULL);\r
+       _tab_object_resize(obj, NULL, obj, NULL);\r
+}\r
+\r
+/////////////////////////////////////////////////////////////\r
+//\r
+// animation function\r
+//\r
+/////////////////////////////////////////////////////////////\r
+\r
+static unsigned int _current_time_get()\r
+{\r
+       struct timeval timev;\r
+\r
+       gettimeofday(&timev, NULL);\r
+       return ((timev.tv_sec * 1000) + ((timev.tv_usec) / 1000));\r
+}\r
+\r
+static void set_evas_map(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)\r
+{\r
+       if(obj == NULL) {\r
+               return;\r
+       }\r
+\r
+       Evas_Map *map = evas_map_new(4);\r
+       if(map == NULL) return;\r
+\r
+       evas_map_smooth_set( map, EINA_TRUE );\r
+       evas_map_util_points_populate_from_object_full( map, obj, 0 );\r
+       evas_object_map_enable_set( obj, EINA_TRUE );\r
+\r
+       evas_map_util_3d_perspective( map, x + w/2, y + h/2, 0, w * 10 );\r
+       evas_map_util_points_populate_from_geometry( map, x, y, w, h, 0 );\r
+\r
+       evas_object_map_set( obj, map );\r
+       evas_map_free( map );\r
+}\r
+\r
+static Eina_Bool move_evas_map(void *data)\r
+{\r
+       double t;\r
+       int dx, dy, dw, dh;\r
+       int px, py, pw, ph;\r
+       int x, y, w, h;\r
+       Animation_Data *ad = (Animation_Data *)data;\r
+       \r
+       t = ELM_MAX(0.0, _current_time_get() - ad->start_time) / 1000;\r
+       dx = ad->tx - ad->fx;\r
+       dy = ad->ty - ad->fy;\r
+       dw = ad->tw - ad->fw;\r
+       dh = ad->th - ad->fh;\r
+\r
+       if (t <= ad->time){\r
+               x = (1 * sin((t / ad->time) * (M_PI / 2)) * dx);\r
+               y = (1 * sin((t / ad->time) * (M_PI / 2)) * dy);\r
+               w = (1 * sin((t / ad->time) * (M_PI / 2)) * dw);\r
+               h = (1 * sin((t / ad->time) * (M_PI / 2)) * dh);\r
+       } else {\r
+               x = dx;\r
+               y = dy;\r
+               w = dw;\r
+               h = dh;\r
+       }\r
+\r
+       px = ad->fx + x;\r
+       py = ad->fy + y;\r
+       pw = ad->fw + w;\r
+       ph = ad->fh + h;\r
+\r
+       if( x == dx && y == dy && w == dw && h == dh ){\r
+               ecore_animator_del(ad->timer);\r
+               ad->timer = NULL;\r
+\r
+               set_evas_map(ad->obj, px, py, pw, ph);\r
+\r
+               if(ad->func != NULL) ad->func(ad->data, ad->obj);\r
+       }else{  \r
+               set_evas_map(ad->obj, px, py, pw, ph);\r
+       }\r
+\r
+       return EXIT_FAILURE;\r
+}\r
+\r
+static void move_object_with_animation(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Evas_Coord x_, Evas_Coord y_, Evas_Coord w_, Evas_Coord h_, double time, void (*func) (void *data, Evas_Object *obj), void *data)\r
+{\r
+       Animation_Data *ad = (Animation_Data *)malloc(sizeof(Animation_Data));\r
+\r
+       ad->obj = obj;\r
+       ad->fx = x;\r
+       ad->fy = y;\r
+       ad->fw = w;\r
+       ad->fh = h;\r
+       ad->tx = x_;\r
+       ad->ty = y_;\r
+       ad->tw = w_;\r
+       ad->th = h_;\r
+       ad->start_time = _current_time_get();\r
+       ad->time = time;\r
+       ad->func = func;\r
+       ad->data = data;\r
+       ad->timer = ecore_animator_add( move_evas_map , ad);\r
+}\r
+\r
+\r
+/////////////////////////////////////////////////////////////\r
+//\r
+// callback function\r
+//\r
+/////////////////////////////////////////////////////////////\r
+\r
+static void print_all_item(Widget_Data *wd)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Evas_Coord x, y, w, h;\r
+\r
+       printf("=========\n");\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               evas_object_geometry_get(item->base, &x, &y, &w, &h);\r
+               printf("label: %s order: %d %d %d %d %d\n", item->label, item->order, x, y, w, h);\r
+               evas_object_show(item->base);\r
+       }\r
+       printf("=========\n");\r
+}\r
+\r
+\r
+static void done_button_cb(void *data, Evas_Object *obj, void *event_info)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+//     print_all_item(wd);\r
+       edje_object_signal_emit(wd->edit_box, "elm,state,hide,edit_box", "elm");\r
+\r
+       wd->edit_mode = EINA_FALSE;\r
+}\r
+\r
+\r
+\r
+///////////////////////////////////////////////////////////////////\r
+//\r
+//  basic utility function\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+\r
+               \r
+static void item_insert_in_bar(Elm_Tab_Item *it, int order)\r
+{      \r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       int check = 0;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->order == order && item != it) check = 1;\r
+       }\r
+\r
+       if(check){\r
+               EINA_LIST_FOREACH(wd->items, l, item){\r
+                       if(item->order > 0 ) elm_table_unpack(wd->box, item->base);\r
+               }\r
+\r
+               EINA_LIST_FOREACH(wd->items, l, item){\r
+                       if(item->order > 0){\r
+                               if(item->order >= order) item->order += 1;\r
+                               elm_table_pack(wd->box, item->base, item->order-1, 0, 1, 1);\r
+                               evas_object_show(item->base);\r
+                       }\r
+               }\r
+       }\r
+       it->order = order;\r
+       elm_table_pack(wd->box, it->base, order-1, 0, 1, 1);\r
+       evas_object_show(it->base);\r
+}\r
+\r
+static void item_delete_in_bar(Elm_Tab_Item *it)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       int i = 1;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item == it){\r
+                       it->order = 0;\r
+                       elm_table_unpack(wd->box, it->base);\r
+                       evas_object_hide(it->base);\r
+               }else{\r
+                       if(item->order > 0){\r
+                               item->order = i;\r
+                               i++;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+static void item_exchange_animation_cb(void *data, Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       wd->animating--;\r
+       if(wd->animating < 0){\r
+               printf("animation error\n");\r
+               wd->animating = 0;\r
+       }\r
+//     printf("animation end : %d\n", wd->animating);\r
+}\r
+\r
+static void item_exchange_in_bar(Elm_Tab_Item *it1, Elm_Tab_Item *it2)\r
+{\r
+       int order;\r
+       Evas_Coord x, y, w, h;\r
+       Evas_Coord x_, y_, w_, h_;\r
+       Widget_Data *wd = elm_widget_data_get(it1->obj);\r
+\r
+       evas_object_geometry_get(wd->moving_item->edit_item, &x, &y, &w, &h);\r
+\r
+//     evas_render_updates_free(evas_render_updates(evas_object_evas_get(wd->moving_obj)));\r
+\r
+       set_evas_map(wd->moving_obj, (wd->x+wd->w/2), (wd->y+wd->h/2), 0, 0);\r
+//     evas_object_del(wd->moving_obj);\r
+//     wd->moving_obj = NULL;\r
+       \r
+       evas_object_geometry_get(it1->base, &x, &y, &w, &h);\r
+       evas_object_geometry_get(it2->base, &x_, &y_, &w_, &h_);\r
+\r
+       wd->animating++;\r
+       move_object_with_animation(it1->base, x, y, w, h, x_, y_, w_, h_, 0.25, item_exchange_animation_cb, wd);\r
+       wd->animating++;\r
+       move_object_with_animation(it2->base, x_, y_, w_, h_, x, y, w, h, 0.25, item_exchange_animation_cb, wd);\r
+\r
+       elm_table_unpack(wd->box, it1->base);\r
+       elm_table_unpack(wd->box, it2->base);\r
+\r
+       order = it1->order;\r
+       it1->order = it2->order;\r
+       it2->order = order;\r
+\r
+       elm_table_pack(wd->box, it1->base, it1->order-1, 0, 1, 1);\r
+       elm_table_pack(wd->box, it2->base, it2->order-1, 0, 1, 1);\r
+}\r
+\r
+static void item_change_animation_cb(void *data, Evas_Object *obj)\r
+{\r
+       Evas_Coord x, y, w, h;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       wd->animating--;\r
+       if(wd->animating < 0){\r
+               printf("animation error\n");\r
+               wd->animating = 0;\r
+       }\r
+//printf("animation end : %d\n", wd->animating);\r
+\r
+       evas_object_geometry_get(obj, &x, &y, &w, &h);\r
+       set_evas_map(obj, x, y, 0, 0);\r
+       evas_object_move(obj, -1000, -1000);\r
+\r
+       evas_object_geometry_get(wd->moving_item->base, &x, &y, &w, &h);\r
+\r
+       evas_object_move(wd->moving_obj, -1000, -1000);\r
+       evas_object_del(wd->moving_obj);\r
+}\r
+\r
+static void item_change_in_bar(Elm_Tab_Item *it)\r
+{\r
+       Evas_Coord x, y, w, h;\r
+       Evas_Coord x_, y_, w_, h_;\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       if(wd == NULL) return;\r
+       if(wd->moving_item == NULL) return;\r
+\r
+       evas_object_geometry_get(wd->moving_item->edit_item, &x, &y, &w, &h);\r
+//     evas_object_geometry_get(it->base, &x, &y, &w, &h);\r
+       set_evas_map(wd->moving_obj, x, y, w, h);\r
+//     evas_object_del(wd->moving_obj);\r
+\r
+       elm_table_unpack(wd->box, it->base);\r
+\r
+       wd->moving_item->order = it->order;\r
+       it->order = 0;\r
+\r
+       elm_table_pack(wd->box, wd->moving_item->base, wd->moving_item->order-1, 0, 1, 1);\r
+       \r
+       evas_object_show(wd->moving_item->base);\r
+               \r
+       evas_render_updates_free(evas_render_updates(evas_object_evas_get(wd->moving_item->base)));\r
+\r
+       evas_object_geometry_get(it->base, &x, &y, &w, &h);\r
+       evas_object_geometry_get(it->edit_item, &x_, &y_, &w_, &h_);\r
+\r
+       wd->animating++;\r
+       move_object_with_animation(it->base, x, y, w, h, x_, y_, w_, h_, 0.25, item_change_animation_cb, wd);\r
+\r
+       evas_object_geometry_get(wd->moving_item->base, &x, &y, &w, &h);\r
+       set_evas_map(wd->moving_item->base, x, y, w, h);\r
+}\r
+\r
+static int selected_box(Elm_Tab_Item *it)\r
+{\r
+       int i = 1;\r
+       int check = 0;\r
+       Evas_Object *icon;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               edje_object_signal_emit(_EDJ(item->base), "elm,state,unselected", "elm");\r
+               item->selected = EINA_FALSE;\r
+               edje_object_part_unswallow(wd->view, item->view);\r
+               evas_object_hide(item->view);\r
+\r
+               icon = edje_object_part_swallow_get(_EDJ(item->base), "elm.swallow.icon");\r
+               if(icon){\r
+//                     if(strcmp(evas_object_type_get(icon), "edje") == 0){\r
+//                             edje_object_signal_emit(icon, "elm,state,unselected", "elm");\r
+//                     }else{\r
+//                             if(_EDJ(icon))\r
+//                                     edje_object_signal_emit(_EDJ(icon), "elm,state,unselected", "elm");\r
+                               evas_object_color_set(icon, 255, 255, 255, 255);\r
+//                     }\r
+               }\r
+\r
+               if(it == item){\r
+                       edje_object_signal_emit(_EDJ(it->base), "elm,state,selected", "elm");\r
+                       edje_object_part_swallow(wd->view, "elm.swallow.view", it->view);\r
+                       evas_object_show(it->view);\r
+\r
+                       if(icon){\r
+//                             if(strcmp(evas_object_type_get(icon), "edje") == 0){\r
+//                                     edje_object_signal_emit(icon, "elm,state,selected", "elm");\r
+//                             }else{\r
+//                                     if(_EDJ(icon))\r
+//                                             edje_object_signal_emit(_EDJ(icon), "elm,state,selected", "elm");\r
+                                       evas_object_color_set(icon, 0, 151, 222, 15);\r
+//                             }\r
+                       }\r
+                       item->selected = EINA_TRUE;\r
+\r
+                       check = 1;\r
+               }\r
+               i++;\r
+       }\r
+\r
+       if(!check) return EXIT_FAILURE;\r
+\r
+       evas_object_smart_callback_call(it->obj, "clicked", it);\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static int sort_cb(const void *d1, const void *d2)\r
+{\r
+       Elm_Tab_Item *item1, *item2;\r
+\r
+       item1 = (Elm_Tab_Item *)d1;\r
+       item2 = (Elm_Tab_Item *)d2;\r
+\r
+       return item1->order > item2->order ? 1 : -1;\r
+}\r
+\r
+static Evas_Object *create_item_layout(Evas_Object *parent, Elm_Tab_Item *it)\r
+{\r
+       Evas_Object *obj;\r
+       Evas_Object *icon;\r
+\r
+       obj = elm_layout_add(parent);\r
+       if(obj == NULL){\r
+               fprintf(stderr, "Cannot load bg edj\n");\r
+               return NULL;\r
+       }\r
+       elm_layout_theme_set(obj, "tabbar", "item", elm_widget_style_get(it->obj));\r
+       evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
+       evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, EVAS_HINT_FILL);\r
+       elm_widget_sub_object_add(it->obj, obj);\r
+\r
+       if (it->label){\r
+               edje_object_part_text_set(_EDJ(obj), "elm.text", it->label);\r
+       }\r
+\r
+       if (it->icon_path){\r
+               icon = elm_icon_add(obj);\r
+               elm_icon_file_set(icon, AQUA_THEME_FILE, it->icon_path);\r
+\r
+               evas_object_size_hint_min_set(icon, 40, 40);\r
+               evas_object_size_hint_max_set(icon, 100, 100);\r
+               evas_object_show(icon);\r
+               edje_object_part_swallow(_EDJ(obj), "elm.swallow.icon", icon);\r
+               it->icon = icon;\r
+       }\r
+\r
+       return obj;\r
+}\r
+\r
+static void edit_item_down_end_cb (void *data, Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+//     evas_render_updates(evas_object_evas_get(wd->moving_obj));\r
+\r
+       wd->animating--;\r
+       if(wd->animating < 0){\r
+               printf("animation error\n");\r
+               wd->animating = 0;\r
+       }\r
+//printf("animation end : %d\n", wd->animating);\r
+}\r
+\r
+static void edit_item_return_cb (void *data, Evas_Object *obj)\r
+{\r
+       Evas_Coord x, y, w, h;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+//     evas_render_updates(evas_object_evas_get(obj));\r
+       evas_object_geometry_get(wd->moving_item->edit_item, &x, &y, &w, &h);\r
+       set_evas_map(obj, x, y, 0, 0);\r
+\r
+       if(wd->move_event != NULL) {\r
+               ecore_event_handler_del(wd->move_event);\r
+               wd->move_event = NULL;\r
+       }\r
+       if(wd->up_event != NULL) {\r
+               ecore_event_handler_del(wd->up_event);\r
+               wd->up_event = NULL;\r
+       }\r
+\r
+       evas_object_data_set(wd->moving_obj, "returning", 0);\r
+\r
+       wd->animating--;\r
+       if(wd->animating < 0){\r
+               printf("animation error\n");\r
+               wd->animating = 0;\r
+       }\r
+//printf("animation end : %d\n", wd->animating);\r
+}\r
+\r
+static Eina_Bool edit_item_move_cb(void *data, int type, void *event_info)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Ecore_Event_Mouse_Move *ev = event_info;\r
+       Evas_Coord x, y, w, h;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       if(wd->animating) return EXIT_FAILURE;\r
+\r
+       evas_object_geometry_get( wd->moving_obj, &x, &y, &w, &h );\r
+\r
+       w *= 2.0;\r
+       h *= 2.0;\r
+\r
+       x = ev->x - w/2;\r
+       y = ev->y - h;\r
+\r
+       set_evas_map(wd->moving_obj, x, y, w, h);\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(wd->moving_item->edit_item == item->edit_item) continue;\r
+               evas_object_geometry_get(item->base, &x, &y, &w, &h);\r
+               if(ev->x > x && ev->x < x+w && ev->y > y && ev->y < y+h){\r
+                       edje_object_signal_emit(_EDJ(item->base), "elm,state,show,glow", "elm");\r
+               }else{\r
+                       edje_object_signal_emit(_EDJ(item->base), "elm,state,hide,glow", "elm");\r
+               }\r
+       }\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static Eina_Bool edit_item_up_cb(void *data, int type, void *event_info)\r
+{\r
+       Ecore_Event_Mouse_Button *ev = event_info;\r
+       Evas_Coord x, y, w, h;\r
+       Evas_Coord x_, y_, w_, h_;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       if(wd->moving_obj)\r
+               if(evas_object_data_get(wd->moving_obj, "returning") == 1) return EXIT_FAILURE; \r
+\r
+       evas_object_color_set(wd->moving_item->edit_item, 255, 255, 255, 255);\r
+\r
+       // check which change or not\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(wd->moving_item->edit_item == item->edit_item) continue;\r
+               if(item->order <= 0) continue;\r
+               evas_object_geometry_get(item->base, &x, &y, &w, &h);\r
+               if(ev->x > x && ev->x < x+w && ev->y > y && ev->y < y+h){\r
+                       edje_object_signal_emit(_EDJ(item->base), "elm,state,hide,glow", "elm");\r
+                       break;  \r
+               }\r
+       }\r
+\r
+       if(item != NULL) {     \r
+               if(wd->moving_item->order > 0){\r
+                       item_exchange_in_bar(wd->moving_item, item);\r
+               }else{\r
+                       item_change_in_bar(item);\r
+               }\r
+\r
+               if(wd->move_event != NULL) {\r
+                       ecore_event_handler_del(wd->move_event);\r
+                       wd->move_event = NULL;\r
+               }\r
+               if(wd->up_event != NULL) {\r
+                       ecore_event_handler_del(wd->up_event);\r
+                       wd->up_event = NULL;\r
+               }\r
+       }else{\r
+               // return moving object to original location\r
+               evas_object_geometry_get(wd->moving_item->edit_item, &x_, &y_, &w_, &h_);\r
+               evas_object_geometry_get( wd->moving_obj, &x, &y, &w, &h );\r
+\r
+               w *= 2.0;\r
+               h *= 2.0;\r
+               x = ev->x - w/2;\r
+               y = ev->y - h;\r
+\r
+               evas_object_data_set(wd->moving_obj, "returning", (void *)1);\r
+               wd->animating++;\r
+               move_object_with_animation(wd->moving_obj, x, y, w, h, x_, y_, w_, h_, 0.25, edit_item_return_cb, wd);\r
+       }\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static void edit_item_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)\r
+{\r
+       Evas_Event_Mouse_Down *ev = event_info;\r
+       Evas_Coord x, y, w, h;\r
+       Evas_Coord x_, y_, w_, h_;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(wd->animating) return;\r
+\r
+       if(wd->up_event == NULL)\r
+               wd->up_event = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, edit_item_up_cb, (void *)wd);\r
+       if(wd->move_event == NULL)\r
+               wd->move_event = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, edit_item_move_cb, (void *)wd);\r
+\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->edit_item == obj) break;\r
+       }\r
+       if(item == NULL) return;\r
+\r
+       wd->moving_item = item;\r
+\r
+       evas_object_color_set(item->edit_item, 100, 100, 100, 255);\r
+       \r
+       if(wd->moving_obj) evas_object_del(wd->moving_obj);\r
+       wd->moving_obj = NULL;\r
+\r
+       wd->moving_obj = create_item_layout(obj, item); \r
+       evas_object_geometry_get(obj, &x, &y, &w, &h);\r
+       evas_object_move(wd->moving_obj, -1000 , -1000);\r
+       evas_object_resize(wd->moving_obj, w, h);\r
+       evas_object_show(wd->moving_obj);\r
+\r
+       w_ = w * 2.0;\r
+       h_ = h * 2.0;\r
+       x_ = ev->output.x - w_/2;\r
+       y_ = ev->output.y - h_;\r
+\r
+       wd->animating++;\r
+       move_object_with_animation(wd->moving_obj, x, y, w, h, x_, y_, w_, h_, 0.1, edit_item_down_end_cb, wd);\r
+}\r
+\r
+static void bar_item_move_end_cb (void *data, Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+//     evas_render_updates(evas_object_evas_get(obj));\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->base == obj) break;\r
+       }\r
+\r
+       wd->animating--;\r
+       if(wd->animating < 0){\r
+               printf("animation error\n");\r
+               wd->animating = 0;\r
+       }\r
+       evas_object_data_set(obj, "animating", 0);\r
+//printf("animation end : %d\n", wd->animating);\r
+}\r
+\r
+\r
+static Eina_Bool bar_item_animation_end_check(void *data)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+//     Evas_Coord x, y, w, h;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+\r
+       if(wd->animating) return EXIT_FAILURE;\r
+\r
+//     evas_object_geometry_get(wd->moving_obj, &x, &y, &w, &h);\r
+//     set_evas_map(wd->moving_obj, x, y, w, h);\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->base == wd->moving_obj) break;\r
+       }\r
+       if(item == NULL) {\r
+               printf("item is NULL\n");\r
+       }else{\r
+               item->order = wd->empty_num;\r
+               wd->empty_num = 0;\r
+               wd->moving_obj = NULL;\r
+       }\r
+       if(wd->bar_move_event != NULL) {\r
+               ecore_event_handler_del(wd->bar_move_event);\r
+               wd->bar_move_event = NULL;\r
+       }\r
+       if(wd->bar_up_event != NULL) {\r
+               ecore_event_handler_del(wd->bar_up_event);\r
+               wd->bar_up_event = NULL;\r
+       }\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static Eina_Bool bar_item_move_cb(void *data, int type, void *event_info)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item, *it;\r
+       Ecore_Event_Mouse_Move *ev = event_info;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       Evas_Coord x, y, w, h, x_, y_, w_, h_;\r
+       int tmp;\r
+\r
+       if(wd->moving_obj == NULL) {\r
+               printf("%s : moving_obj is NULL\n", __func__);\r
+               return EXIT_FAILURE;\r
+       }\r
+       evas_object_geometry_get(wd->moving_obj, &x, &y, &w, &h);\r
+       x = ev->x - w/2;\r
+\r
+       set_evas_map(wd->moving_obj, x, y, w, h);\r
+//     evas_render_updates(evas_object_evas_get(wd->moving_obj));\r
+       \r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->base == wd->moving_obj) {\r
+                       it = item;\r
+                       continue;\r
+               }\r
+               if(evas_object_data_get(item->base, "animating") == 1) continue;\r
+               evas_object_geometry_get(item->base, &x, &y, &w, &h);\r
+               if(ev->x > x && ev->x < x+w){\r
+                       evas_object_geometry_get(wd->moving_obj, &x_, &y_, &w_, &h_);\r
+                       evas_object_move(wd->moving_obj, x, y);\r
+\r
+                       tmp = wd->empty_num;\r
+                       wd->empty_num = item->order;\r
+                       item->order = tmp;\r
+\r
+                       elm_table_unpack(wd->box, item->base);\r
+                       elm_table_unpack(wd->box, wd->moving_obj);\r
+                       elm_table_pack(wd->box, item->base, item->order-1, 0, 1, 1);\r
+                       elm_table_pack(wd->box, wd->moving_obj, wd->empty_num-1, 0, 1, 1);\r
+\r
+                       wd->animating++;\r
+                       evas_object_data_set(item->base, "animating", (void *)1);\r
+                       move_object_with_animation(item->base, x, y, w, h, x_, y_, w_, h_, 0.25, bar_item_move_end_cb, wd);\r
+               }\r
+       }\r
+       \r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static Eina_Bool bar_item_up_cb(void *data, int type, void *event_info)\r
+{\r
+       Evas_Coord tx, x, y, w, h;\r
+       Ecore_Event_Mouse_Button *ev = event_info;\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+\r
+       evas_object_geometry_get(wd->moving_obj, &x, &y, &w, &h);\r
+       tx = ev->x - w/2;\r
+       move_object_with_animation(wd->moving_obj, tx, y, w, h, x, y, w, h, 0.25, NULL, NULL);\r
+//     set_evas_map(wd->moving_obj, x, y, w, h);\r
+       \r
+       ecore_timer_add(0.1, bar_item_animation_end_check, wd);\r
+\r
+       return EXIT_SUCCESS;\r
+}\r
+\r
+static void bar_item_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)\r
+{\r
+       Widget_Data *wd = (Widget_Data *)data;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(wd->animating) return;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->base == obj) break;\r
+       }\r
+\r
+       if(wd->edit_mode){\r
+               if(wd->bar_up_event != NULL || wd->bar_move_event != NULL) return;\r
+               \r
+               wd->moving_obj = obj;\r
+\r
+               wd->empty_num = item->order;\r
+\r
+               if(wd->bar_up_event == NULL)\r
+                       wd->bar_up_event = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, bar_item_up_cb, (void *)wd);\r
+               if(wd->bar_move_event == NULL)\r
+                       wd->bar_move_event = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, bar_item_move_cb, (void *)wd);\r
+       }else{\r
+               selected_box(item);\r
+       }\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////\r
+//\r
+//  API function\r
+//\r
+////////////////////////////////////////////////////////////////////\r
+\r
+/**\r
+ * Add a new tab object\r
+ *\r
+ * @param parent The parent object\r
+ * @return The new object or NULL if it cannot be created\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Evas_Object *elm_tabbar_add(Evas_Object *parent) {\r
+       Evas_Object *obj = NULL;\r
+       Widget_Data *wd = NULL;\r
+       Evas_Coord x, y, w, h;\r
+       Evas_Object *r_button;\r
+\r
+       wd = ELM_NEW(Widget_Data);\r
+       wd->evas = evas_object_evas_get(parent);\r
+       if (wd->evas == NULL) return NULL;\r
+       obj = elm_widget_add(wd->evas);\r
+       if(obj == NULL) return NULL;\r
+       elm_widget_type_set(obj, "tabbar");\r
+       elm_widget_sub_object_add(parent, obj);\r
+       elm_widget_data_set(obj, wd);\r
+       elm_widget_del_hook_set(obj, _del_hook);\r
+       elm_widget_theme_hook_set(obj, _theme_hook);\r
+\r
+       // initialization\r
+       wd->parent = parent;\r
+       evas_object_geometry_get(parent, &x, &y, &w, &h);\r
+       wd->object = obj;\r
+       wd->x = x;\r
+       wd->y = y;\r
+       wd->w = w;\r
+       wd->h = h;\r
+       wd->num = 0;\r
+       wd->animating = 0;\r
+       wd->edit_mode = EINA_FALSE;\r
+\r
+       wd->view = edje_object_add(wd->evas);\r
+       _elm_theme_object_set(obj, wd->view, "tabbar", "view", "default");\r
+       if(wd->view == NULL) {\r
+               printf("Cannot load bg edj\n");\r
+               return NULL;\r
+       }\r
+       evas_object_show(wd->view);\r
+\r
+       // edit box\r
+       wd->edit_box = edje_object_add(wd->evas);\r
+       _elm_theme_object_set(obj, wd->edit_box, "tabbar", "edit_box", "default");\r
+       if(wd->edit_box == NULL) {\r
+               printf("Cannot load bg edj\n");\r
+               return NULL;\r
+       }\r
+       evas_object_show(wd->edit_box);\r
+\r
+       wd->navigation = elm_navigationbar_add(wd->edit_box);\r
+       r_button = elm_button_add(wd->navigation);\r
+       elm_button_label_set(r_button, "Done");\r
+       evas_object_smart_callback_add(r_button, "clicked", done_button_cb, wd);\r
+       elm_navigationbar_push(wd->navigation, "Configure", NULL, r_button, NULL, NULL);\r
+       edje_object_part_swallow(wd->edit_box, "elm.swallow.navigation", wd->navigation);\r
+       \r
+       wd->edit_table = elm_table_add(wd->edit_box);\r
+       edje_object_part_swallow(wd->edit_box, "elm.swallow.table", wd->edit_table);\r
+\r
+       /* load background edj */\r
+       wd->edje = edje_object_add(wd->evas);\r
+//     snprintf(buf, sizeof(buf), "bg_portrait_%d", wd->view_slot_num);\r
+       _elm_theme_object_set(obj, wd->edje, "tabbar", "base", "default");\r
+       if(wd->edje == NULL) {\r
+               printf("Cannot load bg edj\n");\r
+               return NULL;\r
+       }\r
+       evas_object_show(wd->edje);\r
+\r
+       // initialization\r
+       evas_object_event_callback_add(wd->edje, EVAS_CALLBACK_RESIZE, _tab_object_resize, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _tab_object_move, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _tab_object_show, obj);\r
+       evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _tab_object_hide, obj);\r
+\r
+       // items container\r
+       wd->box = elm_table_add(wd->edje);\r
+       evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);\r
+       evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);\r
+       edje_object_part_swallow(wd->edje, "elm.swallow.items", wd->box);       \r
+       elm_widget_sub_object_add(obj, wd->box);\r
+\r
+       //FIXME\r
+       //      evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);\r
+\r
+       evas_object_smart_member_add(wd->view, obj);\r
+       evas_object_smart_member_add(wd->edit_box, obj);\r
+       elm_widget_resize_object_set(obj, wd->edje);\r
+       evas_object_smart_member_add(wd->box, obj);\r
+\r
+       // initialization\r
+       _sizing_eval(obj);\r
+\r
+       return obj;\r
+}\r
+\r
+/**\r
+ * Add new item\r
+ *\r
+ * @param obj The tab object\r
+ * @param      icon The icon of item\r
+ * @param      label The label of item\r
+ * @param      func Callback function of item\r
+ * @param      data The data of callback function\r
+ * @return The item of tab\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tabbar_item_add(Evas_Object *obj, const char *icon_path, const char *label, Evas_Object *view)\r
+{\r
+       Elm_Tab_Item *it;\r
+       Widget_Data *wd;\r
+\r
+       if(obj == NULL) {\r
+               fprintf(stderr, "Invalid argument: tab object is NULL\n");\r
+               return NULL;\r
+       }\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL) {\r
+               fprintf(stderr, "Cannot get smart data\n");\r
+               return NULL;\r
+       }\r
+\r
+       it = ELM_NEW(Elm_Tab_Item);\r
+    if(it == NULL) return NULL;\r
+    wd->items = eina_list_append(wd->items, it);\r
+    it->obj = obj;\r
+    it->label = eina_stringshare_add(label);\r
+       it->icon_path = icon_path;\r
+    it->badge = 0;\r
+       it->view = view;\r
+\r
+       it->base = create_item_layout(wd->edje, it);\r
+       evas_object_event_callback_add(it->base, EVAS_CALLBACK_MOUSE_DOWN, bar_item_down_cb, wd);       \r
+       evas_object_show(it->base);\r
+\r
+       it->edit_item = create_item_layout(wd->edje, it);\r
+       evas_object_event_callback_add(it->edit_item, EVAS_CALLBACK_MOUSE_DOWN, edit_item_down_cb, wd);\r
+       evas_object_show(it->edit_item);\r
+\r
+       wd->num += 1;\r
+       it->order = wd->num;\r
+       \r
+       elm_table_pack(wd->box, it->base, wd->num-1, 0, 1, 1);\r
+\r
+       elm_table_pack(wd->edit_table, it->edit_item, (wd->num-1)%4, (wd->num-1)/4, 1, 1);\r
+               \r
+       if(wd->num == 1) selected_box(it);\r
+\r
+       return it;\r
+}\r
+\r
+#if 0\r
+\r
+/**\r
+ * Delete item from tab by index\r
+ *\r
+ * @param      it The item of tab\r
+\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tabbar_item_del(Elm_Tab_Item *it)\r
+{\r
+       int check = 0;\r
+       int i = 1;\r
+       char buf[MAX_ARGS];\r
+       Widget_Data *wd;\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+\r
+       if(it->obj == NULL){\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return;\r
+       }\r
+       wd = elm_widget_data_get(it->obj);\r
+       if(wd == NULL){\r
+               printf("Cannot get smart data\n");\r
+               return;\r
+       }\r
+\r
+       edje_object_part_unswallow(wd->edje, it->base);\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(check){\r
+                       edje_object_part_unswallow(wd->edje, item->base);\r
+                       snprintf(buf, sizeof(buf), "slot_%d", i-1);\r
+                       edje_object_part_swallow(wd->edje, buf, item->base);\r
+               }\r
+               if(it == item){\r
+                       check = 1;\r
+               }\r
+               i++;\r
+       }\r
+\r
+       eina_stringshare_del(it->label);\r
+       if (it->icon) evas_object_del(it->icon);\r
+       evas_object_del(it->base);\r
+       evas_object_del(it->edit_item);\r
+       wd->items = eina_list_remove(wd->items, it);\r
+       wd->num = wd->num - 1;\r
+}\r
+\r
+#endif\r
+\r
+/**\r
+ * Select item in tabbar\r
+ *\r
+ * @param      it The item of tabbar\r
+\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tabbar_item_select(Elm_Tab_Item *it)\r
+{\r
+       if(it->obj == NULL) return;\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       if(wd == NULL) return;\r
+\r
+       if(!wd->edit_mode){\r
+               selected_box(it);\r
+       }\r
+}\r
+\r
+/**\r
+ * Get the icon of item\r
+ *\r
+ * @param      it The item of tabbar\r
+ * @return The icon object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Evas_Object *elm_tabbar_item_icon_get(Elm_Tab_Item *it)\r
+{\r
+       return it->icon;\r
+}\r
+\r
+/**\r
+ * Get the label of item\r
+ *\r
+ * @param      it The item of tabbar\r
+ * @return the label of item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI const char *elm_tabbar_item_label_get(Elm_Tab_Item *it)\r
+{\r
+       return it->label;\r
+}\r
+\r
+/**\r
+ * Set the label of item\r
+ *\r
+ * @param      it The item of tabbar\r
+ * @param      label The label of item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tabbar_item_label_set(Elm_Tab_Item *it, const char *label)\r
+{\r
+       if(!it->base) return;\r
+\r
+       edje_object_part_text_set(it->base, "elm.text", label);\r
+}\r
+\r
+#if 0\r
+\r
+/**\r
+ * Set the badge of item.\r
+ *\r
+ * @param      it The item of tab\r
+ * @param      badge The number in item badge. If -1, badge is not visible. Otherwise, it is just number.\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_item_badge_set(Elm_Tab_Item *it, const int badge)\r
+{\r
+       char buf[MAX_ARGS];\r
+\r
+       if(!it->base) return;\r
+\r
+       if(it->badge == badge) return;\r
+\r
+       if(badge < -1) {\r
+               printf("elm_tab_item_badge_set : second parameter range not availble. (-1 <= badge < 1000)\n");\r
+               return;\r
+       }\r
+\r
+       it->badge = badge;\r
+\r
+       if(badge == -1){\r
+               edje_object_signal_emit(it->base, "elm,badge,unvisible", "elm");\r
+       }else{\r
+               if(it->badge > 1000) {\r
+                       printf("Badge Number is too large. ( badge < 1000)\n");\r
+                       return;\r
+               }\r
+\r
+               snprintf(buf, sizeof(buf), "%d", it->badge);\r
+               edje_object_part_text_set(it->base, "elm.text.badge", buf);\r
+\r
+               if(it->badge > 100){\r
+                       edje_object_signal_emit(it->base, "elm,badge,text_normal", "elm");\r
+               }else{\r
+                       edje_object_signal_emit(it->base, "elm,badge,text_small", "elm");\r
+               }\r
+               edje_object_signal_emit(it->base, "elm,badge,visible", "elm");\r
+       }\r
+}\r
+\r
+/**\r
+ * Get the selected item.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_selected_item_get(Evas_Object *obj)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(item->selected) return item;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+/**\r
+ * Get the first item.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_first_item_get(Evas_Object *obj)\r
+{\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       return eina_list_data_get(wd->items);\r
+}\r
+\r
+/**\r
+ * Get the last item.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_last_item_get(Evas_Object *obj)\r
+{\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       return eina_list_data_get(eina_list_last(wd->items));\r
+}\r
+\r
+/**\r
+ * Get the items.\r
+ *\r
+ * @param      obj The tab object\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Eina_List *elm_tab_items_get(Evas_Object *obj)\r
+{\r
+       if(obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       return wd->items;\r
+}\r
+\r
+/**\r
+ * Get the previous item.\r
+ *\r
+ * @param      it The item of tab\r
+ * @return     The previous item of the parameter item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_item_prev(Elm_Tab_Item *it)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(it->obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(it == item){\r
+                       l = eina_list_prev(l);\r
+                       if(!l) return NULL;\r
+                       return eina_list_data_get(l);\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+/**\r
+ * Get the next item.\r
+ *\r
+ * @param      obj The tab object\r
+ * @return     The next item of the parameter item\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Elm_Tab_Item *elm_tab_item_next(Elm_Tab_Item *it)\r
+{\r
+       const Eina_List *l;\r
+       Elm_Tab_Item *item;\r
+\r
+       if(it->obj == NULL) return NULL;\r
+\r
+       Widget_Data *wd = elm_widget_data_get(it->obj);\r
+       if(!wd || !wd->items) return NULL;\r
+\r
+       EINA_LIST_FOREACH(wd->items, l, item){\r
+               if(it == item){\r
+                       l = eina_list_next(l);\r
+                       if(!l) return NULL;\r
+                       return eina_list_data_get(l);\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+/**\r
+ * Move the tab object\r
+ *\r
+ * @param      obj The tab object\r
+ * @param      direction the direction of movement\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_move(Evas_Object *obj, int direction)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       retm_if(obj == NULL, "Invalid argument: tab object is NULL\n");\r
+       wd = elm_widget_data_get(obj);\r
+       retm_if(wd == NULL, "Cannot get smart data\n");\r
+\r
+       if(direction == ELM_TAB_MOVE_LEFT){\r
+               _move_obj_to_left(wd);\r
+       }else if(direction == ELM_TAB_MOVE_RIGHT){\r
+               _move_obj_to_right(wd);\r
+       }\r
+}\r
+\r
+/**\r
+ * Set the edit mode of the tab disable\r
+ *\r
+ * @param      obj The tab object\r
+ * @param      disable if 1, edit mode is disable.\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tab_edit_disable_set(Evas_Object *obj, Eina_Bool disable)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       retm_if(obj == NULL, "Invalid argument: tab object is NULL\n");\r
+       wd = elm_widget_data_get(obj);\r
+       retm_if(wd == NULL, "Cannot get smart data\n");\r
+\r
+       wd->edit_disable = disable;\r
+}\r
+\r
+/**\r
+ * Get the availability for the edit mode of the tab\r
+ *\r
+ * @param      obj The tab object\r
+ * @return  disable or not\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI Eina_Bool elm_tab_edit_disable_get(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       if(obj == NULL) {\r
+               printf("Invalid argument: tab object is NULL\n");\r
+               return -1;\r
+       }\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL) {\r
+               printf("Cannot get smart data\n");\r
+               return -1;\r
+       }\r
+\r
+       return wd->edit_disable;\r
+}\r
+\r
+#endif\r
+\r
+/**\r
+ * Start edit mode\r
+ *\r
+ * @param      The tab object\r
+\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tabbar_edit_start(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd;\r
+\r
+       if(obj == NULL){\r
+               fprintf(stderr, "Invalid argument: tab object is NULL\n");\r
+               return;\r
+       }\r
+       wd = elm_widget_data_get(obj);\r
+       if(wd == NULL){\r
+               fprintf(stderr, "Cannot get smart data\n");\r
+               return;\r
+       }\r
+\r
+       edje_object_signal_emit(wd->edit_box, "elm,state,show,edit_box", "elm");\r
+\r
+       wd->edit_mode = EINA_TRUE;\r
+}\r
+\r
+/**\r
+ * Set item in bar\r
+ *\r
+ * @param      it The item of tab\r
+ * @param      bar EINA_TRUE or EINA_FALSE\r
+ *\r
+ * @ingroup Tab\r
+ */\r
+EAPI void elm_tabbar_item_visible_set(Elm_Tab_Item *it, Eina_Bool bar)\r
+{\r
+       Eina_Bool check = EINA_TRUE;\r
+       \r
+       if(it->order <= 0) check = EINA_FALSE;\r
+       \r
+       if(check == bar) return;\r
+\r
+       if(bar){\r
+               item_insert_in_bar(it, 0);\r
+       }else{\r
+               item_delete_in_bar(it); \r
+       }\r
+}\r
diff --git a/src/lib/elm_timepicker.c b/src/lib/elm_timepicker.c
new file mode 100644 (file)
index 0000000..793af1c
--- /dev/null
@@ -0,0 +1,610 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Timepicker Timepicker
+ * @ingroup Elementary
+ *
+ * This is a time picker.
+ */
+
+
+#define PICKER_DRAG_BOUND (10)
+
+#define MAX_HOUR (12)
+#define MAX_HOUR2 (23)
+#define MAX_DIGIT (9)
+#define MAX_DIGIT2 (59)
+
+enum {
+       PICKER_HRS,
+       PICKER_MIN,
+       PICKER_SUB,
+       PICKER_AMPM,
+       PICKER_MAX
+};
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data {
+       Evas_Object *base;
+       Evas_Object *pickers[PICKER_MAX];
+
+       int hrs, min, sec;
+       Eina_Bool is_pm;
+
+       Eina_Bool ampm;
+       Eina_Bool seconds;
+};
+
+static inline Eina_Bool _is_time_valid(int hrs, int min, int sec);
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _disable_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _update_ampm(Evas_Object *obj);
+static void _update_seconds(Evas_Object *obj);
+static void _update_picker(Evas_Object *picker, int nth);
+static void _update_all(Evas_Object *obj);
+static void _hrs_reload(Evas_Object *picker, Eina_Bool ampm);
+static void _digit_reload(Evas_Object *picker, Eina_Bool seconds, int max);
+static Evas_Object *_hrs_add(Evas_Object *ly, const char *part, Eina_Bool ampm);
+static Evas_Object *_digit_add(Evas_Object *ly, const char *part, unsigned char max);
+static Evas_Object *_ampm_add(Evas_Object *ly, const char *part);
+static void _callback_init(Evas_Object *obj);
+static void _pickers_add(Evas_Object *obj);
+static void _pickers_del(Evas_Object *obj);
+static void _changed(Evas_Object *picker, Evas_Object *child, Evas_Object *obj);
+static void _overflow_cb(void *data, Evas_Object *obj, void *event_info);
+static void _underflow_cb(void *data, Evas_Object *obj, void *event_info);
+static void _hrs_changed_cb(void *data, Evas_Object *obj, void *event_info);
+static void _min_changed_cb(void *data, Evas_Object *obj, void *event_info);
+static void _sub_changed_cb(void *data, Evas_Object *obj, void *event_info);
+static void _ampm_changed_cb(void *data, Evas_Object *obj, void *event_info);
+
+static inline Eina_Bool
+_is_time_valid(int hrs, int min, int sec)
+{
+       if (hrs < 0 || hrs > 23 || min < 0 || min > 59 || sec < 0 || sec > 59)
+               return EINA_FALSE;
+       return EINA_TRUE;
+}
+
+static void
+_del_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       _pickers_del(obj);
+       free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       _pickers_del(obj);
+       _elm_theme_object_set(obj, wd->base, "timepicker", "base", elm_widget_style_get(obj));
+       _pickers_add(obj);
+
+       _update_ampm(obj);
+       _update_seconds(obj);
+       _sizing_eval(obj);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+
+               if (!wd) return;
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
+       elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+       evas_object_size_hint_min_set(obj, minw, minh);
+       evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_update_ampm(Evas_Object *obj)
+{
+       const char *sig;
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       if (wd->ampm)
+               sig = "elm,state,ampm,visible";
+
+       else
+               sig = "elm,state,ampm,hidden";
+
+       _hrs_reload(wd->pickers[PICKER_HRS], wd->ampm);
+       edje_object_signal_emit(wd->base, sig, "elm");
+       _update_all(obj);
+}
+
+static void
+_update_seconds(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       const char *sig;
+       if (!wd) return;
+
+       if (wd->seconds)
+               sig = "elm,state,sec,visible";
+       else
+               sig = "elm,state,sec,hidden";
+
+       _digit_reload(wd->pickers[PICKER_MIN], wd->seconds, 5);
+       _digit_reload(wd->pickers[PICKER_SUB], wd->seconds, MAX_DIGIT);
+
+       edje_object_signal_emit(wd->base, sig, "elm");
+       _update_all(obj);
+}
+
+static void
+_update_picker(Evas_Object *picker, int nth)
+{
+       const Eina_List *l;
+       Elm_Picker_Item *item;
+       int i;
+       l = elm_picker_items_get(picker);
+       for (i = 0; i < nth; i++) {
+               l = l->next;
+               if (!l) break;
+       }
+
+       item = eina_list_data_get(l);
+
+       elm_picker_item_selected_set(item);
+}
+
+static void
+_update_all(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       int hrs;
+       if (!wd) return;
+
+       hrs = wd->hrs;
+       if (wd->ampm)
+               hrs = wd->hrs % 12;
+
+       _update_picker(wd->pickers[PICKER_HRS],  hrs);
+       if (wd->hrs >= 12)
+               wd->is_pm = 1;
+       else
+               wd->is_pm = 0;
+       _update_picker(wd->pickers[PICKER_AMPM], wd->is_pm);
+
+       if (wd->seconds) {
+               _update_picker(wd->pickers[PICKER_MIN],  wd->min);
+               _update_picker(wd->pickers[PICKER_SUB],  wd->sec);
+       } else {
+               _update_picker(wd->pickers[PICKER_MIN],  wd->min / 10);
+               _update_picker(wd->pickers[PICKER_SUB],  wd->min % 10);
+       }
+       _sizing_eval(obj);
+}
+
+static void
+_hrs_reload(Evas_Object *picker, Eina_Bool ampm)
+{
+       int i, max;
+       char buf[8];
+       Elm_Picker_Item *item;
+
+       item = elm_picker_first_item_get(picker);
+
+       while (item) {
+               elm_picker_item_del(item);
+               item = elm_picker_first_item_get(picker);
+       }
+
+       if (ampm) {
+               i = 1;
+               snprintf(buf, 8, "%02d", MAX_HOUR);
+               elm_picker_item_append(picker, buf, NULL, NULL);
+               max = MAX_HOUR - 1;
+       } else {
+               i = 0;
+               max = MAX_HOUR2;
+       }
+
+       for (; i <= max; i++) {
+               snprintf(buf, 8, "%02d", i);
+               elm_picker_item_append(picker, buf, NULL, NULL);
+       }
+}
+
+static void
+_digit_reload(Evas_Object *picker, Eina_Bool seconds, int max)
+{
+       int i;
+       char buf[8];
+       Elm_Picker_Item *item;
+       const char *exp;
+
+       item = elm_picker_first_item_get(picker);
+
+       while (item) {
+               elm_picker_item_del(item);
+               item = elm_picker_first_item_get(picker);
+       }
+
+       if (seconds) max = MAX_DIGIT2;
+       if (max >= 10) exp = "%02d";
+       else exp = "%d";
+
+       for (i = 0; i <= max; i++) {
+               snprintf(buf, 8, exp, i);
+               elm_picker_item_append(picker, buf, NULL, NULL);
+       }
+}
+
+static Evas_Object *
+_hrs_add(Evas_Object *ly, const char *part, Eina_Bool ampm)
+{
+       int i, max;
+       char buf[8];
+       Evas_Object *eo;
+       eo = elm_picker_add(ly);
+
+       if (ampm) {
+               i = 1;
+               snprintf(buf, 8, "%02d", MAX_HOUR);
+               elm_picker_item_append(eo, buf, NULL, NULL);
+               max = MAX_HOUR - 1;
+       } else {
+               i = 0;
+               max = MAX_HOUR2;
+       }
+
+       for (; i <= max; i++) {
+               snprintf(buf, 8, "%02d", i);
+               elm_picker_item_append(eo, buf, NULL, NULL);
+       }
+       if (part)
+               edje_object_part_swallow(ly, part, eo);
+       return eo;
+}
+
+static Evas_Object *
+_digit_add(Evas_Object *ly, const char *part, unsigned char max)
+{
+       int i;
+       char buf[8];
+       Evas_Object *eo;
+       eo = elm_picker_add(ly);
+       for (i = 0; i <= max; i++) {
+               snprintf(buf, 8, "%d", i);
+               elm_picker_item_append(eo, buf, NULL, NULL);
+       }
+       if (part)
+               edje_object_part_swallow(ly, part, eo);
+       return eo;
+}
+
+static Evas_Object *
+_ampm_add(Evas_Object *ly, const char *part)
+{
+       Evas_Object *eo;
+       eo = elm_picker_add(ly);
+       elm_object_style_set(eo, "timepicker/ampm");
+       elm_picker_item_append(eo, "AM", NULL, NULL);
+       elm_picker_item_append(eo, "PM", NULL, NULL);
+       if (part)
+               edje_object_part_swallow(ly, part, eo);
+       return eo;
+}
+
+static void
+_callback_init(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       evas_object_data_set(wd->pickers[PICKER_HRS], "child", wd->pickers[PICKER_MIN]);
+       evas_object_data_set(wd->pickers[PICKER_MIN], "child", wd->pickers[PICKER_SUB]);
+       evas_object_data_set(wd->pickers[PICKER_SUB], "child", NULL);
+       evas_object_data_set(wd->pickers[PICKER_AMPM], "child", wd->pickers[PICKER_HRS]);
+       evas_object_data_set(wd->pickers[PICKER_HRS], "parent", wd->pickers[PICKER_AMPM]);
+       evas_object_data_set(wd->pickers[PICKER_MIN], "parent", wd->pickers[PICKER_HRS]);
+       evas_object_data_set(wd->pickers[PICKER_SUB], "parent", wd->pickers[PICKER_MIN]);
+
+       evas_object_smart_callback_add(wd->pickers[PICKER_HRS], "overflowed", _overflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_HRS], "underflowed", _underflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_MIN], "overflowed", _overflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_MIN], "underflowed", _underflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_SUB], "overflowed", _overflow_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_SUB], "underflowed", _underflow_cb, obj);
+
+       evas_object_smart_callback_add(wd->pickers[PICKER_HRS], "changed", _hrs_changed_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_MIN], "changed", _min_changed_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_SUB], "changed", _sub_changed_cb, obj);
+       evas_object_smart_callback_add(wd->pickers[PICKER_AMPM], "changed", _ampm_changed_cb, obj);
+}
+
+static void
+_pickers_add(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       wd->pickers[PICKER_HRS] = _hrs_add(wd->base, "elm.swallow.hour", EINA_TRUE);
+       wd->pickers[PICKER_MIN] = _digit_add(wd->base, "elm.swallow.min", 5);
+       wd->pickers[PICKER_SUB] = _digit_add(wd->base, "elm.swallow.sub", MAX_DIGIT);
+       wd->pickers[PICKER_AMPM] = _ampm_add(wd->base, "elm.swallow.ampm");
+       edje_object_signal_emit(wd->base, "elm,state,ampm,visible", "elm");
+       wd->ampm = EINA_TRUE;
+
+       _callback_init(obj);
+}
+
+static void
+_pickers_del(Evas_Object *obj)
+{
+       int i = 0;
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       for (i = 0; i < PICKER_MAX; i++) {
+               if (wd->pickers[i]) {
+                       evas_object_del(wd->pickers[i]);
+                       wd->pickers[i] = NULL;
+               }
+       }
+}
+
+static void
+_changed(Evas_Object *picker, Evas_Object *child, Evas_Object *obj)
+{
+       int c1, c2 = 0;
+       c1 = (int)(evas_object_data_get(picker, "carryon"));
+       evas_object_data_set(picker, "carryon", (void *)0);
+
+       if (child) {
+               c2 = (int)(evas_object_data_get(child, "carryon"));
+               evas_object_data_set(child, "carryon", (void *)0);
+       }
+
+       if (!c1 && !c2)
+               evas_object_smart_callback_call(obj, "changed", NULL);
+}
+
+static void
+_overflow_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       Evas_Object *eo;
+       eo = evas_object_data_get(obj, "parent");
+       if (eo) {
+               elm_picker_next(eo);
+               evas_object_data_set(obj, "carryon", (void *)1);
+       }
+}
+
+static void
+_underflow_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       Evas_Object *eo;
+       eo = evas_object_data_get(obj, "parent");
+       if (eo) {
+               elm_picker_prev(eo);
+               evas_object_data_set(obj, "carryon", (void *)1);
+       }
+}
+
+static void
+_hrs_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       const char *hrs;
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Object *child;
+       if (!wd) return;
+
+       hrs = elm_picker_item_label_get(event_info);
+       wd->hrs = atoi(hrs);
+
+       if (wd->ampm) {
+               wd->hrs %= 12;
+               if (wd->is_pm)
+                       wd->hrs += 12;
+       }
+
+       child = evas_object_data_get(obj, "child");
+       _changed(obj, child, data);
+}
+
+static void
+_min_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       const char *min;
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Object *child;
+       if (!wd) return;
+
+       min = elm_picker_item_label_get(event_info);
+
+       if (wd->seconds) {
+               wd->min = atoi(min);
+       } else {
+               wd->min = wd->min % 10;
+               wd->min += atoi(min) * 10;
+       }
+
+       child = evas_object_data_get(obj, "child");
+       _changed(obj, child, data);
+}
+
+static void
+_sub_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       const char *sub;
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Object *child;
+       if (!wd) return;
+
+       sub = elm_picker_item_label_get(event_info);
+
+       if (wd->seconds) {
+               wd->sec = atoi(sub);
+       } else {
+               wd->min = wd->min - wd->min % 10;
+               wd->min += atoi(sub);
+       }
+
+       child = evas_object_data_get(obj, "child");
+       _changed(obj, child, data);
+}
+
+static void
+_ampm_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+       const char *ampm;
+       Widget_Data *wd = elm_widget_data_get(data);
+       Evas_Object *child;
+       if (!wd) return;
+
+       ampm = elm_picker_item_label_get(event_info);
+
+       wd->hrs = (wd->hrs) % 12;
+       if (!strcmp(ampm, "AM")) {
+               wd->is_pm = 0;
+       } else {
+               wd->is_pm = 1;
+               wd->hrs += 12;
+       }
+
+       child = evas_object_data_get(obj, "child");
+       _changed(obj, child, data);
+}
+
+/**
+ * Add a new timepicker to the parent
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Timepicker
+ */
+EAPI Evas_Object *
+elm_timepicker_add(Evas_Object *parent)
+{
+       Evas_Object *obj;
+       Evas *e;
+       Widget_Data *wd;
+
+       wd = ELM_NEW(Widget_Data);
+       e = evas_object_evas_get(parent);
+       obj = elm_widget_add(e);
+       elm_widget_type_set(obj, "timepicker");
+       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_disable_hook_set(obj, _disable_hook);
+
+       wd->base = edje_object_add(e);
+       _elm_theme_object_set(obj, wd->base, "timepicker", "base", "default");
+       elm_widget_resize_object_set(obj, wd->base);
+       _pickers_add(obj);
+       _sizing_eval(obj);
+       return obj;
+}
+
+/**
+ * Set selected time of the timepicker
+ *
+ * @param obj The timepicker object
+ * @param hrs The hours to set
+ * @param min The minutes to set
+ * @param sec The seconds to set
+ *
+ * @ingroup Timepicker
+ */
+EAPI void
+elm_timepicker_time_set(Evas_Object *obj, int hrs, int min, int sec)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       if (!_is_time_valid(hrs, min, sec)) return;
+
+       wd->hrs = hrs;
+       wd->min = min;
+       wd->sec = sec;
+
+       _update_all(obj);
+}
+
+/**
+ * Get selected time of the timepicker
+ *
+ * @param obj The timepicker object
+ * @param hrs The Pointer to the variable to get the selected hours
+ * @param min The Pointer to the variable to get the selected minute
+ * @param sec The Pointer to the variable to get the selected seconds
+ *
+ * @ingroup Timepicker
+ */
+EAPI void
+elm_timepicker_time_get(Evas_Object *obj, int *hrs, int *min, int *sec)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       if (hrs)
+               *hrs = wd->hrs;
+       if (min)
+               *min = wd->min;
+       if (sec)
+               *sec = wd->sec;
+}
+
+/**
+ * Set if the timepicker show hours in military or am/pm mode
+ *
+ * @param obj The timepicker object
+ * @param am_pm Bool option for the hours mode
+ *
+ * @ingroup Timepicker
+ */
+EAPI void
+elm_timepicker_show_am_pm_set(Evas_Object *obj, Eina_Bool am_pm)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       if (wd->ampm != am_pm) {
+               wd->ampm = am_pm;
+               _update_ampm(obj);
+       }
+}
+
+/**
+ * Set if the timepicker show seconds picker or not
+ *
+ * @param obj The timepicker object
+ * @param am_pm Bool option for the show seconds picker
+ *
+ * @ingroup Timepicker
+ */
+EAPI void
+elm_timepicker_show_seconds_set(Evas_Object *obj, Eina_Bool seconds)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       if (wd->seconds != seconds) {
+               wd->seconds = seconds;
+               _update_seconds(obj);
+       }
+}
diff --git a/src/lib/elm_titlebar.c b/src/lib/elm_titlebar.c
new file mode 100644 (file)
index 0000000..172c910
--- /dev/null
@@ -0,0 +1,245 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+
+/**
+ * @defgroup Titlebar Titlebar
+ * @ingroup Elementary
+ *
+ * This is a titlebar widget. It can contain simple label,icon 
+ * and other objects.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *tbar;
+   Evas_Object *icon;
+   Evas_Object *end;
+   const char *label;
+};
+
+static const char *widtype = NULL;
+static void _del_hook(Evas_Object * obj);
+static void _theme_hook(Evas_Object * obj);
+static void _sizing_eval(Evas_Object * obj);
+static void _changed_size_hints(void *data, Evas * e, Evas_Object * obj, void *event_info);
+static void _sub_del(void *data, Evas_Object * obj, void *event_info);
+
+static void
+_del_hook(Evas_Object * obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->label) eina_stringshare_del(wd->label);
+   free(wd);
+}
+
+static void
+_theme_hook(Evas_Object * obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   _elm_theme_object_set(obj, wd->tbar, "titlebar", "base", elm_widget_style_get(obj));
+   edje_object_part_text_set(wd->tbar, "elm.text", wd->label);
+   edje_object_scale_set(wd->tbar, elm_widget_scale_get(obj) * _elm_config->scale);
+   _sizing_eval(obj);
+}
+
+static void
+_sizing_eval(Evas_Object * obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+   if (!wd) return;
+   edje_object_size_min_calc(wd->tbar, &minw, &minh);
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_changed_size_hints(void *data, Evas * e __UNUSED__, Evas_Object * obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Widget_Data *wd = elm_widget_data_get(data);
+   if (!wd) return;
+   _sizing_eval(data);
+}
+
+static void
+_sub_del(void *data __UNUSED__, Evas_Object * obj, void *event_info)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Object *sub = event_info;
+   if (!wd) return;
+   evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+   if (sub == wd->icon)
+     {
+        edje_object_signal_emit(wd->tbar, "elm,state,icon,hidden", "elm");
+        wd->icon = NULL;
+        edje_object_message_signal_process(wd->tbar);
+     }
+   else if (sub == wd->end) wd->end = NULL;
+   _sizing_eval(obj);
+}
+
+/**
+ * Add a new titlebar object.
+ *
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup Titlebar
+ */
+EAPI Evas_Object *
+elm_titlebar_add(Evas_Object * parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   obj = elm_widget_add(e);
+   ELM_SET_WIDTYPE(widtype, "titlebar");
+   elm_widget_type_set(obj, "titlebar");
+   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);
+
+   wd->tbar = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->tbar, "titlebar", "base", "default");
+   elm_widget_resize_object_set(obj, wd->tbar);
+
+   evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * This set's the label in titlebar object.
+ *
+ * @param obj The titlebar object
+ * @param label The label text
+ *
+ * @ingroup Titlebar
+ */
+EAPI void
+elm_titlebar_label_set(Evas_Object * obj, const char *label)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   eina_stringshare_replace(&wd->label, label);
+   edje_object_part_text_set(wd->tbar, "elm.text", label);
+   _sizing_eval(obj);
+}
+
+/**
+ * This get's the label packed in titlebar object.
+ *
+ * @param obj The titlebar object
+ * @return label text
+ *
+ * @ingroup Titlebar
+ */
+EAPI const char *
+elm_titlebar_label_get(Evas_Object * obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return wd->label;
+}
+
+/**
+ * This set's the icon object in titlebar object.
+ *
+ * @param obj The titlebar object
+ * @param icon The icon object
+ *
+ * @ingroup Titlebar
+ */
+EAPI void
+elm_titlebar_icon_set(Evas_Object * obj, Evas_Object * icon)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->icon == icon) return;
+   if (wd->icon) evas_object_del(wd->icon);
+   wd->icon = icon;
+   if (icon)
+     {
+       elm_widget_sub_object_add(obj, icon);
+       edje_object_part_swallow(wd->tbar, "elm.swallow.icon", icon);
+       evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_signal_emit(wd->tbar, "elm,state,icon,visible", "elm");
+       edje_object_message_signal_process(wd->tbar);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * This get's the icon object packed in titlebar object.
+ *
+ * @param obj The titlebar object
+ * @return The icon object
+ *
+ * @ingroup Titlebar
+ */
+EAPI Evas_Object *
+elm_titlebar_icon_get(Evas_Object * obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return wd->icon;
+}
+
+/**
+ * This set's the end object in titlebar object.
+ *
+ * @param obj The titlebar object
+ * @param end The end object
+ *
+ * @ingroup Titlebar
+ */
+EAPI void
+elm_titlebar_end_set(Evas_Object * obj, Evas_Object * end)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return;
+   if (wd->end == end) return;
+   if (wd->end) evas_object_del(wd->end);
+   wd->end = end;
+   if (end)
+     {
+       elm_widget_sub_object_add(obj, end);
+       evas_object_event_callback_add(end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
+                                      _changed_size_hints, obj);
+       edje_object_part_swallow(wd->tbar, "elm.swallow.end", end);
+     }
+   _sizing_eval(obj);
+}
+
+/**
+ * This get's the end object packed in titlebar object.
+ *
+ * @param obj The titlebar object
+ * @return The icon object
+ *
+ * @ingroup Titlebar
+ */
+EAPI Evas_Object *
+elm_titlebar_end_get(Evas_Object * obj)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   if (!wd) return NULL;
+   return wd->end;
+}
diff --git a/src/lib/elm_wipercontrol.c b/src/lib/elm_wipercontrol.c
new file mode 100644 (file)
index 0000000..22280bf
--- /dev/null
@@ -0,0 +1,120 @@
+/*\r
+ * @defgroup WiperControl WiperControl\r
+ * @ingroup Elementary\r
+ *\r
+ * This is a wipercontrol.\r
+ */\r
+\r
+#include <Elementary.h>\r
+#include "elm_priv.h"\r
+\r
+typedef struct _Widget_Data Widget_Data;\r
+\r
+struct _Widget_Data\r
+{\r
+       Evas_Object *sd;\r
+};\r
+\r
+static void _del_hook(Evas_Object *obj);\r
+static void _theme_hook(Evas_Object *obj);\r
+static void _disable_hook(Evas_Object *obj);\r
+static void _sizing_eval(Evas_Object *obj);\r
+\r
+static void\r
+_del_hook(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if (!wd) return;\r
+       free(wd);\r
+}\r
+\r
+\r
+/*\r
+ * FIXME:\r
+ */\r
+static void\r
+_theme_hook(Evas_Object *obj)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if (!wd) return;\r
+\r
+       _elm_theme_object_set(obj,wd->sd, "wipercontrol", "base", elm_widget_style_get(obj));\r
+\r
+       _sizing_eval(obj);\r
+\r
+       evas_object_show (wd->sd);\r
+}\r
+\r
+static void\r
+_sizing_eval(Evas_Object *obj)\r
+{\r
+//     Widget_Data *wd = elm_widget_data_get(obj);\r
+}\r
+\r
+/**\r
+ * Set below content to the wipercontrol\r
+ *\r
+ * @param[in] obj Wipercontrol object\r
+ * @param[in] content Custom object\r
+ * @ingroup WiperControl\r
+ */\r
+EAPI void\r
+elm_wipercontrol_below_content_set (Evas_Object *obj, Evas_Object *content)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if (!wd) return;\r
+       if (!content) return;\r
+\r
+       edje_object_part_swallow (wd->sd, "content.below.swallow", content);\r
+}\r
+\r
+/**\r
+ * Set above content to the wipercontrol\r
+ *\r
+ * @param[in] obj Wipercontrol object\r
+ * @param[in] content Custom object\r
+ * @ingroup WiperControl\r
+ */\r
+EAPI void\r
+elm_wipercontrol_above_content_set (Evas_Object *obj, Evas_Object *content)\r
+{\r
+       Widget_Data *wd = elm_widget_data_get(obj);\r
+       if (!wd) return;\r
+       if (!content) return;\r
+\r
+       edje_object_part_swallow (wd->sd, "content.above.swallow", content);\r
+}\r
+\r
+/**\r
+ * Add a new wipercontrol to the parent\r
+ * @param parent The parent object\r
+ * @return The new object or NULL if it cannot be created\r
+ * @ingroup WiperControl\r
+ */\r
+EAPI Evas_Object *\r
+elm_wipercontrol_add(Evas_Object *parent)\r
+{\r
+       Evas_Object *obj;\r
+       Evas *e;\r
+       Widget_Data *wd;\r
+\r
+       wd = ELM_NEW(Widget_Data);\r
+       e = evas_object_evas_get(parent);\r
+       obj = elm_widget_add(e);\r
+       elm_widget_type_set(obj, "wipercontrol");\r
+       elm_widget_sub_object_add(parent, obj);\r
+       elm_widget_data_set(obj, wd);\r
+       elm_widget_del_hook_set(obj, _del_hook);\r
+       elm_widget_theme_hook_set(obj, _theme_hook);\r
+       elm_widget_can_focus_set(obj, 0);\r
+\r
+       wd->sd = edje_object_add(e);\r
+\r
+       _elm_theme_object_set(obj,wd->sd, "wipercontrol", "base", "default");\r
+\r
+       elm_widget_resize_object_set(obj, wd->sd);\r
+\r
+       _sizing_eval(obj);\r
+\r
+       return obj;\r
+}\r
diff --git a/src/lib/elm_zoomcontrols.c b/src/lib/elm_zoomcontrols.c
new file mode 100644 (file)
index 0000000..ccdf376
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ *
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#include <Elementary.h>
+#include "elm_priv.h"
+
+#define ZC_DEFAULT_RANGE 5
+/**
+ * @defgroup ZoomControls ZoomControls
+ * @ingroup Elementary
+ *
+ * This is a zoomcontrols. Press it and run some function.
+ */
+
+typedef struct _Widget_Data Widget_Data;
+
+struct _Widget_Data
+{
+   Evas_Object *base;
+   int count;
+   int range;
+   int downdefaultstate;
+   int updefaultstate;
+   int downdisabledstate;
+   int updisabledstate;
+   int downdisabledfocusedstate;
+   int updisabledfocusedstate;
+};
+
+
+static void _del_hook(Evas_Object *obj);
+static void _theme_hook(Evas_Object *obj);
+static void _disable_hook(Evas_Object *obj);
+static void _sizing_eval(Evas_Object *obj);
+static void _signal_down_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _signal_up_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
+
+static void
+_del_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+       free(wd);
+}
+
+static void
+_theme_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if (!wd) return;
+
+       _elm_theme_object_set(obj, wd->base, "zoomcontrols", "base", elm_widget_style_get(obj));
+       edje_object_message_signal_process(wd->base);
+       edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
+       _sizing_eval(obj);
+}
+
+static void
+_disable_hook(Evas_Object *obj)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if(wd->downdisabledstate)
+       {
+               edje_object_signal_emit(obj, "elm,state,down,disabled", "elm");
+       }
+       else if(wd->downdefaultstate)
+       {
+               edje_object_signal_emit(wd->base, "elm,state,down,enabled", "elm");
+       }
+       
+       if(wd->updisabledstate)
+       {
+               edje_object_signal_emit(obj, "elm,state,up,disabled", "elm");
+       }
+       else if(wd->updefaultstate)
+       {
+               edje_object_signal_emit(wd->base, "elm,state,up,enabled", "elm");
+       }
+}
+
+static void
+_sizing_eval(Evas_Object *obj)
+{
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
+   Evas_Coord w, h;
+   
+   if (!wd) return;
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+   edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);   
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+
+   evas_object_size_hint_min_get(obj, &w, &h);
+   if (w > minw) minw = w;
+   if (h > minw) minh = h;
+
+   evas_object_size_hint_min_set(obj, minw, minh);
+   evas_object_size_hint_max_set(obj, maxw, maxh);
+}
+
+static void
+_signal_down_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+       if (!wd) return;
+
+       if((wd->downdefaultstate == 0) && (wd->downdisabledstate == 1))
+       {
+               return;
+       }
+       else
+       {
+               edje_object_signal_emit(wd->base, "elm,state,down,selected", "elm");
+       }
+
+       if(wd->range <= 0)
+               wd->range = ZC_DEFAULT_RANGE;
+       
+       if(wd->count > -(wd->range))
+       {
+               if(wd->count == wd->range)
+               {
+                       wd->updisabledstate = 0;
+                       wd->updefaultstate = 1;
+                       edje_object_signal_emit(wd->base, "elm,state,up,enabled", "elm");
+                
+               }
+               wd->count--;    
+               printf("smart callback call (down)\n");
+               evas_object_smart_callback_call(data, "down_clicked", NULL);
+       }
+
+       printf("count %d\n", wd->count);
+
+       if(wd->count == -(wd->range))
+       { 
+               printf("down disabled \n");
+               wd->downdisabledstate = 1;
+               wd->downdefaultstate = 0;
+               edje_object_signal_emit(wd->base, "elm,state,down,disabled", "elm");
+       }
+}
+static void
+_signal_up_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+       if (!wd) return;
+
+       if((wd->updefaultstate == 0) && (wd->updisabledstate == 1))
+       {
+               return;
+       }
+       else
+       {
+               edje_object_signal_emit(wd->base, "elm,state,up,selected", "elm");
+       }
+
+       if(wd->range <= 0)
+               wd->range = ZC_DEFAULT_RANGE;
+       
+       if(wd->count < wd->range)
+       {
+               if(wd->count == -(wd->range))
+               {
+                       wd->downdisabledstate = 0;
+                       wd->downdefaultstate = 1;
+                       edje_object_signal_emit(wd->base, "elm,state,down,enabled", "elm");
+               }
+               wd->count++;
+               printf("smart callback call (up)\n");
+               evas_object_smart_callback_call(data, "up_clicked", NULL);
+
+       }
+
+       printf("count %d\n", wd->count);
+}
+static void
+_signal_down_unclicked(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+
+       if(wd->range <= 0)
+               wd->range = ZC_DEFAULT_RANGE;
+       
+       if(wd->count == -(wd->range))
+       { 
+               printf("down enabled \n");
+               wd->downdisabledstate = 1;
+               wd->downdefaultstate = 0;
+               edje_object_signal_emit(wd->base, "elm,state,down,disabled", "elm");
+       }
+       else if(wd->count > -(wd->range))
+       {
+               edje_object_signal_emit(wd->base, "elm,state,down,enabled", "elm");
+       }     
+}
+static void
+_signal_up_unclicked(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+       Widget_Data *wd = elm_widget_data_get(data);
+
+       if(wd->range <= 0)
+               wd->range = ZC_DEFAULT_RANGE;
+       
+       if(wd->count == wd->range)
+       {
+               printf("up enabled\n");
+               wd->updisabledstate = 1;
+               wd->updefaultstate = 0;
+               edje_object_signal_emit(wd->base, "elm,state,up,disabled", "elm");
+       }
+       else if(wd->count < wd->range)
+       {
+               edje_object_signal_emit(wd->base, "elm,state,up,enabled", "elm");
+       }     
+}
+
+/**
+ * Add a new zoomcontrols to the parent
+ * @param parent The parent object
+ * @return The new object or NULL if it cannot be created
+ *
+ * @ingroup ZoomControls
+ */
+EAPI Evas_Object *
+elm_zoomcontrols_add(Evas_Object *parent)
+{
+   Evas_Object *obj;
+   Evas *e;
+   Widget_Data *wd;
+
+   wd = ELM_NEW(Widget_Data);
+   e = evas_object_evas_get(parent);
+   obj = elm_widget_add(e);
+   elm_widget_type_set(obj, "zoomcontrols");
+   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_disable_hook_set(obj, _disable_hook);
+   
+   wd->base = edje_object_add(e);
+   _elm_theme_object_set(obj, wd->base, "zoomcontrols", "base", "default");
+
+   wd->count = 0;
+   wd->range = 0;
+   wd->downdefaultstate = 1;
+   wd->updefaultstate = 1;
+   wd->downdisabledstate = 0;
+   wd->updisabledstate = 0;
+   wd->downdisabledfocusedstate = 0;
+   wd->updisabledfocusedstate = 0;
+
+   edje_object_signal_callback_add(wd->base, "elm,action,down,click", "", _signal_down_clicked, obj);
+   edje_object_signal_callback_add(wd->base, "elm,action,up,click", "", _signal_up_clicked, obj);
+   edje_object_signal_callback_add(wd->base, "elm,action,down,unclick", "", _signal_down_unclicked, obj);
+   edje_object_signal_callback_add(wd->base, "elm,action,up,unclick", "", _signal_up_unclicked, obj);
+   
+   elm_widget_resize_object_set(obj, wd->base);
+
+   _sizing_eval(obj);
+   return obj;
+}
+
+/**
+ * Set the range used in the zoomcontrols
+ * 
+ * @param obj The zoomcontrols object
+ * @param range The value will limit count that each button of zoomcontrols is clicked 
+ *
+ * @ingroup ZoomControls
+ */
+EAPI void
+elm_zoomcontrols_range_set(Evas_Object *obj, int range)
+{
+       Widget_Data *wd = elm_widget_data_get(obj);
+       if(!wd)
+               return;
+       
+       if(range <= 0)
+               return;
+
+       wd->range = range;
+}
diff --git a/src/lib/els_hor_scroller.c b/src/lib/els_hor_scroller.c
new file mode 100644 (file)
index 0000000..358645c
--- /dev/null
@@ -0,0 +1,2396 @@
+#include <Elementary.h>
+#include "elm_priv.h"
+#include "els_pan.h"
+#include "els_hor_scroller.h"
+
+#define SMART_NAME "els_hor_scroller"
+#define API_ENTRY Hor_Smart_Data *sd; sd = evas_object_smart_data_get(obj); if ((!obj) || (!sd) || (evas_object_type_get(obj) && strcmp(evas_object_type_get(obj), SMART_NAME)))
+#define INTERNAL_ENTRY Hor_Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
+typedef struct _Hor_Smart_Data Hor_Smart_Data;
+
+#define EVTIME 1
+//#define SCROLLDBG 1
+#define SMART_SCROLLER 1
+#define SMART_MOVE_THRESHOLD 100
+
+#ifdef SMART_SCROLLER
+       #define EVENT_Q_MAX 200
+       #define NR_OF_FRAMES 60.0f
+       #define GEOMETRY_TAG    "geo"
+       #define DATA_TAG        "data"
+       //#define NUMBERS_OF_AVERAGE_QUEUE      "NUMBERS_OF_AVERAGE_QUEUE"
+       #define NUMBERS_OF_AVERAGE_QUEUE        4
+#endif
+
+#define ENABLE_MULITPAGE_MOVING        0
+
+struct _Hor_Smart_Data
+{
+   Evas_Coord   x, y, w, h;
+
+   Evas_Object *smart_obj;
+   Evas_Object *child_obj;
+   Evas_Object *pan_obj;
+   Evas_Object *edje_obj;
+   Evas_Object *event_obj;
+
+   Elm_Very_Smart_Scroller_Policy hbar_flags, vbar_flags;
+
+   struct {
+      Evas_Coord x, y;
+      Evas_Coord sx, sy;
+      Evas_Coord dx, dy;
+      Evas_Coord bx, by;
+      Evas_Coord ax, ay;
+      Evas_Coord bx0, by0;
+      Evas_Coord b0x, b0y;
+      Evas_Coord b2x, b2y;
+      struct {
+        Evas_Coord    x, y;
+        double        timestamp;
+      } history[20];
+      double anim_start;
+      double anim_start2;
+      double anim_start3;
+      double onhold_vx, onhold_vy, onhold_tlast, onhold_vxe, onhold_vye;
+      Evas_Coord hold_x, hold_y;
+      Ecore_Timer *hold_animator;
+      Ecore_Animator *onhold_animator;
+      Ecore_Animator *momentum_animator;
+      Ecore_Animator *bounce_x_animator;
+      Ecore_Animator *bounce_y_animator;
+      Evas_Coord locked_x, locked_y;
+      unsigned char now : 1;
+      unsigned char dragged : 1;
+      unsigned char dir_x : 1;
+      unsigned char dir_y : 1;
+      unsigned char dir_none : 1;
+      unsigned char locked : 1;
+      unsigned char bounce_x_hold : 1;
+      unsigned char bounce_y_hold : 1;
+   } down;
+
+   struct {
+      Evas_Coord w, h;
+   } child;
+   struct {
+      Evas_Coord x, y;
+   } step, page;
+
+   struct {
+      void (*set) (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+      void (*get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+      void (*max_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+      void (*child_size_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+   } pan_func;
+
+   struct {
+      struct {
+         Evas_Coord start, end;
+         double t_start, t_end;
+         Ecore_Animator *animator;
+      } x, y;
+   } scrollto;
+
+   double pagerel_h, pagerel_v;
+   Evas_Coord pagesize_h, pagesize_v;
+
+   unsigned char hbar_visible : 1;
+   unsigned char vbar_visible : 1;
+   unsigned char extern_pan : 1;
+   unsigned char one_dir_at_a_time : 1;
+   unsigned char hold : 1;
+   unsigned char freeze : 1;
+   unsigned char bouncemex : 1;
+   unsigned char bouncemey : 1;
+   unsigned char bounce_horiz : 1;
+   unsigned char bounce_vert : 1;
+
+#ifdef SMART_SCROLLER
+       int event_queue[EVENT_Q_MAX];
+       int consumer_queue[EVENT_Q_MAX];
+       int producer;
+       int resaler;
+       int consumer;
+       int status;
+       int pprev_x;
+       int prev_x;
+       int cur_x;
+       int total_width;
+       int special_prev_x;
+       int special_cur_x;
+       int resaler_continue;
+       int move_cnt;
+       int x_pos;
+       int done;
+       Ecore_Timer *timer;
+       Ecore_Timer *special_timer;
+#endif
+};
+
+/* local subsystem functions */
+static void _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info);
+static void _smart_pan_pan_changed_hook(void *data, Evas_Object *obj, void *event_info);
+static void _smart_event_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static Eina_Bool  _smart_hold_animator(void *data);
+static Eina_Bool  _smart_momentum_animator(void *data);
+static void _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static Eina_Bool  _smart_onhold_animator(void *data);
+static void _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _smart_edje_drag_v_start(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _smart_edje_drag_v_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _smart_edje_drag_v(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _smart_edje_drag_h_start(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _smart_edje_drag_h_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _smart_edje_drag_h(void *data, Evas_Object *obj, const char *emission, const char *source);
+static void _smart_scrollbar_read(Hor_Smart_Data *sd);
+static void _smart_scrollbar_reset(Hor_Smart_Data *sd);
+static int  _smart_scrollbar_bar_h_visibility_adjust(Hor_Smart_Data *sd);
+static int  _smart_scrollbar_bar_v_visibility_adjust(Hor_Smart_Data *sd);
+static void _smart_scrollbar_bar_visibility_adjust(Hor_Smart_Data *sd);
+static void _smart_scrollbar_size_adjust(Hor_Smart_Data *sd);
+static void _smart_reconfigure(Hor_Smart_Data *sd);
+static void _smart_add(Evas_Object *obj);
+static void _smart_del(Evas_Object *obj);
+static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
+static void _smart_show(Evas_Object *obj);
+static void _smart_hide(Evas_Object *obj);
+static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
+static void _smart_clip_set(Evas_Object *obj, Evas_Object *clip);
+static void _smart_clip_unset(Evas_Object *obj);
+static void _smart_init(void);
+
+/* local subsystem globals */
+static Evas_Smart *_smart = NULL;
+
+/* externally accessible functions */
+Evas_Object *
+hor_elm_smart_scroller_add(Evas *evas)
+{
+   _smart_init();
+   return evas_object_smart_add(evas, _smart);
+}
+
+void
+hor_elm_smart_scroller_child_set(Evas_Object *obj, Evas_Object *child)
+{
+   Evas_Coord w, h;
+   Evas_Object *o;
+
+   API_ENTRY return;
+   if (sd->child_obj)
+     {
+       _elm_smart_pan_child_set(sd->pan_obj, NULL);
+       evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_DEL, _smart_child_del_hook, sd);
+     }
+
+   sd->child_obj = child;
+   if (!child) return;
+
+   if (!sd->pan_obj)
+     {
+       o = _elm_smart_pan_add(evas_object_evas_get(obj));
+       sd->pan_obj = o;
+       evas_object_smart_callback_add(o, "changed", _smart_pan_changed_hook, sd);
+       evas_object_smart_callback_add(o, "pan_changed", _smart_pan_pan_changed_hook, sd);
+       evas_object_show(o);
+       edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", o);
+     }
+
+   sd->pan_func.set = _elm_smart_pan_set;
+   sd->pan_func.get = _elm_smart_pan_get;
+   sd->pan_func.max_get = _elm_smart_pan_max_get;
+   sd->pan_func.child_size_get = _elm_smart_pan_child_size_get;
+
+   evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _smart_child_del_hook, sd);
+   _elm_smart_pan_child_set(sd->pan_obj, sd->child_obj);
+   sd->pan_func.child_size_get(sd->pan_obj, &w, &h);
+   sd->child.w = w;
+   sd->child.h = h;
+   _smart_scrollbar_size_adjust(sd);
+   _smart_scrollbar_reset(sd);
+}
+
+void
+hor_elm_smart_scroller_extern_pan_set(Evas_Object *obj, Evas_Object *pan,
+                            void (*pan_set) (Evas_Object *obj, Evas_Coord x, Evas_Coord y),
+                            void (*pan_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
+                            void (*pan_max_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
+                            void (*pan_child_size_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y))
+{
+   API_ENTRY return;
+
+   hor_elm_smart_scroller_child_set(obj, NULL);
+   if (sd->extern_pan)
+     {
+       if (sd->pan_obj)
+         {
+            edje_object_part_unswallow(sd->edje_obj, sd->pan_obj);
+            sd->pan_obj = NULL;
+         }
+     }
+   else
+     {
+       if (sd->pan_obj)
+         {
+            evas_object_del(sd->pan_obj);
+            sd->pan_obj = NULL;
+         }
+     }
+   if (!pan)
+     {
+       sd->extern_pan = 0;
+       return;
+     }
+
+   sd->pan_obj = pan;
+   sd->pan_func.set = pan_set;
+   sd->pan_func.get = pan_get;
+   sd->pan_func.max_get = pan_max_get;
+   sd->pan_func.child_size_get = pan_child_size_get;
+   sd->extern_pan = 1;
+   evas_object_smart_callback_add(sd->pan_obj, "changed", _smart_pan_changed_hook, sd);
+   evas_object_smart_callback_add(sd->pan_obj, "pan_changed", _smart_pan_pan_changed_hook, sd);
+   edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
+   evas_object_show(sd->pan_obj);
+}
+
+void
+hor_elm_smart_scroller_custom_edje_file_set(Evas_Object *obj, char *file, char *group)
+{
+   API_ENTRY return;
+
+   edje_object_file_set(sd->edje_obj, file, group);
+   if (sd->pan_obj)
+     edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
+   sd->vbar_visible = !sd->vbar_visible;
+   sd->hbar_visible = !sd->hbar_visible;
+   _smart_scrollbar_bar_visibility_adjust(sd);
+   if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
+   else if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
+   else
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,hbar", "elm");
+   if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
+   else if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
+   else
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm");
+}
+
+static void
+_smart_anim_start(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "animate,start", NULL);
+}
+
+static void
+_smart_anim_stop(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "animate,stop", NULL);
+}
+
+static void
+_smart_drag_start(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "drag,start", NULL);
+}
+
+static void
+_smart_drag_stop(Evas_Object *obj)
+{
+   evas_object_smart_callback_call(obj, "drag,stop", NULL);
+}
+
+static Eina_Bool
+_smart_scrollto_x_animator(void *data)
+{
+   Hor_Smart_Data *sd = data;
+   Evas_Coord px, py;
+   double t, tt;
+
+   t = ecore_loop_time_get();
+   tt = (t - sd->scrollto.x.t_start) / (sd->scrollto.x.t_end - sd->scrollto.x.t_start);
+   tt = 1.0 - tt;
+   tt = 1.0 - (tt * tt);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   px = (sd->scrollto.x.start * (1.0 - tt)) +
+     (sd->scrollto.x.end * tt);
+   if (t >= sd->scrollto.x.t_end)
+     {
+        px = sd->scrollto.x.end;
+        hor_elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+        sd->scrollto.x.animator = NULL;
+        if (!sd->scrollto.y.animator)
+          _smart_anim_stop(sd->smart_obj);
+        return 0;
+     }
+   hor_elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+   return 1;
+}
+
+static void
+_smart_scrollto_x(Hor_Smart_Data *sd, double t_in, Evas_Coord pos_x)
+{
+   Evas_Coord px, py, x, y, w, h;
+   double t;
+
+   if (sd->freeze) return;
+   if (t_in <= 0.0)
+     {
+        hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        hor_elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+        x = pos_x;
+        hor_elm_smart_scroller_child_region_show(sd->smart_obj, x, y, w, h);
+        return;
+     }
+   t = ecore_loop_time_get();
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   sd->scrollto.x.start = px;
+   sd->scrollto.x.end = pos_x;
+   sd->scrollto.x.t_start = t;
+   sd->scrollto.x.t_end = t + t_in;
+   hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   hor_elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   hor_elm_smart_scroller_child_region_show(sd->smart_obj, x, y, w, h);
+   if (!sd->scrollto.x.animator)
+     {
+        if (!sd->scrollto.y.animator)
+          _smart_anim_start(sd->smart_obj);
+        sd->scrollto.x.animator = ecore_animator_add(_smart_scrollto_x_animator, sd);
+     }
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+     }
+   sd->bouncemex = 0;
+}
+
+static Eina_Bool
+_smart_scrollto_y_animator(void *data)
+{
+   Hor_Smart_Data *sd = data;
+   Evas_Coord px, py;
+   double t, tt;
+
+   t = ecore_loop_time_get();
+   tt = (t - sd->scrollto.y.t_start) / (sd->scrollto.y.t_end - sd->scrollto.y.t_start);
+   tt = 1.0 - tt;
+   tt = 1.0 - (tt * tt);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   py = (sd->scrollto.y.start * (1.0 - tt)) +
+     (sd->scrollto.y.end * tt);
+   if (t >= sd->scrollto.y.t_end)
+     {
+        py = sd->scrollto.y.end;
+        hor_elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+        sd->scrollto.y.animator = NULL;
+        if (!sd->scrollto.x.animator)
+          _smart_anim_stop(sd->smart_obj);
+        return 0;
+     }
+   hor_elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
+
+   return 1;
+}
+
+static void
+_smart_scrollto_y(Hor_Smart_Data *sd, double t_in, Evas_Coord pos_y)
+{
+   Evas_Coord px, py, x, y, w, h;
+   double t;
+
+   if (sd->freeze) return;
+   if (t_in <= 0.0)
+     {
+        hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        hor_elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+        y = pos_y;
+        hor_elm_smart_scroller_child_region_show(sd->smart_obj, x, y, w, h);
+        return;
+     }
+   t = ecore_loop_time_get();
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   sd->scrollto.y.start = py;
+   sd->scrollto.y.end = pos_y;
+   sd->scrollto.y.t_start = t;
+   sd->scrollto.y.t_end = t + t_in;
+   hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   hor_elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   hor_elm_smart_scroller_child_region_show(sd->smart_obj, x, y, w, h);
+   if (!sd->scrollto.y.animator)
+     {
+        if (!sd->scrollto.x.animator)
+          _smart_anim_start(sd->smart_obj);
+        sd->scrollto.y.animator = ecore_animator_add(_smart_scrollto_y_animator, sd);
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+     }
+   sd->bouncemey = 0;
+}
+
+static Eina_Bool
+_smart_do_page(Hor_Smart_Data *sd)
+{
+   if ((sd->pagerel_h == 0.0) && (sd->pagesize_h == 0) &&
+       (sd->pagerel_v == 0.0) && (sd->pagesize_v == 0))
+     return 0;
+   return 1;
+}
+
+static Evas_Coord
+_smart_page_x_get(Hor_Smart_Data *sd, int offset)
+{
+   Evas_Coord x, y, w, h, cw, ch;
+
+   hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   hor_elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+
+// HERE:: One-page moving
+#if 0
+       printf("before offset : %d, x : %d\n", offset, x);
+   if (offset > 0) 
+   {
+       x = x + (sd->pagesize_h);
+       x = x / (sd->pagesize_h);
+       x = x * (sd->pagesize_h);
+   }
+   else if (offset < 0)
+   {
+       if ((x % sd->pagesize_h) == 0) x -= (sd->pagesize_h / 2);
+       x = x / (sd->pagesize_h);
+       x = x * (sd->pagesize_h);
+   }
+   else
+   {
+          printf("offset = 0 -----> cur_x - prev_x [%d]\n", sd->cur_x - sd->prev_x);
+       if (sd->cur_x - sd->prev_x < 0) x += (sd->pagesize_h);
+          else if (sd->cur_x - sd->prev_x > 0) x -= (sd->pagesize_h) / 2;
+       x = x / (sd->pagesize_h);
+       x = x * (sd->pagesize_h);
+   }
+#endif
+
+   x += offset;
+
+   if (sd->pagerel_h > 0.0)
+     {
+        x = x + (w * sd->pagerel_h * 0.5);
+        x = x / (w * sd->pagerel_h);
+        x = x * (w * sd->pagerel_h);
+     }
+   else if (sd->pagesize_h > 0)
+     {
+        x = x + (sd->pagesize_h * 0.5);
+        x = x / (sd->pagesize_h);
+        x = x * (sd->pagesize_h);
+     }
+   if (x < 0) x = 0;
+   else if ((x + w) > cw) x = cw - w;
+   return x;
+}
+
+static Evas_Coord
+_smart_page_y_get(Hor_Smart_Data *sd, int offset)
+{
+   Evas_Coord x, y, w, h, cw, ch;
+
+   hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   hor_elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+   sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+
+   y += offset;
+
+   if (sd->pagerel_v > 0.0)
+     {
+        y = y + (h * sd->pagerel_v * 0.5);
+        y = y / (h * sd->pagerel_v);
+        y = y * (h * sd->pagerel_v);
+     }
+   else if (sd->pagesize_v > 0)
+     {
+        y = y + (sd->pagesize_v * 0.5);
+        y = y / (sd->pagesize_v);
+        y = y * (sd->pagesize_v);
+     }
+   if (y < 0) y = 0;
+   else if ((y + h) > ch) y = ch - h;
+   return y;
+}
+
+static void
+_smart_page_adjust(Hor_Smart_Data *sd)
+{
+   Evas_Coord x, y, w, h;
+
+   if (!_smart_do_page(sd)) return;
+
+   hor_elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
+
+   x = _smart_page_x_get(sd, 0);
+   y = _smart_page_y_get(sd, 0);
+
+   hor_elm_smart_scroller_child_region_show(sd->smart_obj, x, y, w, h);
+}
+
+static Eina_Bool
+_smart_bounce_x_animator(void *data)
+{
+   Hor_Smart_Data *sd;
+   Evas_Coord x, y, dx;
+   double t, p, dt;
+
+   sd = data;
+   t = ecore_loop_time_get();
+   dt = t - sd->down.anim_start2;
+   if (dt >= 0.0)
+     {
+       dt = dt / _elm_config->thumbscroll_bounce_friction;
+       if (dt > 1.0) dt = 1.0;
+       p = 1.0 - ((1.0 - dt) * (1.0 - dt));
+        hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        dx = sd->down.b2x - sd->down.bx;
+       dx = (dx * p);
+       x = sd->down.bx + dx;
+        hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+        if (dt >= 1.0)
+          {
+             if (sd->down.momentum_animator)
+               sd->down.bounce_x_hold = 1;
+             sd->down.bounce_x_animator = NULL;
+             sd->bouncemex = 0;
+             return 0;
+          }
+     }
+   return 1;
+}
+
+static Eina_Bool
+_smart_bounce_y_animator(void *data)
+{
+   Hor_Smart_Data *sd;
+   Evas_Coord x, y, dy;
+   double t, p, dt;
+
+   sd = data;
+   t = ecore_loop_time_get();
+   dt = t - sd->down.anim_start3;
+   if (dt >= 0.0)
+     {
+       dt = dt / _elm_config->thumbscroll_bounce_friction;
+       if (dt > 1.0) dt = 1.0;
+       p = 1.0 - ((1.0 - dt) * (1.0 - dt));
+        hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+        dy = sd->down.b2y - sd->down.by;
+       dy = (dy * p);
+       y = sd->down.by + dy;
+        hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+        if (dt >= 1.0)
+          {
+             if (sd->down.momentum_animator)
+               sd->down.bounce_y_hold = 1;
+             sd->down.bounce_y_animator = NULL;
+             sd->bouncemey = 0;
+             return 0;
+          }
+     }
+   return 1;
+}
+
+static Eina_Bool
+_smart_momentum_animator(void *data)
+{
+   Hor_Smart_Data *sd;
+   double t, dt, p;
+   Evas_Coord x, y, dx, dy, px, py;
+
+   sd = data;
+   t = ecore_loop_time_get();
+   dt = t - sd->down.anim_start;
+   if (dt >= 0.0)
+     {
+       dt = dt / _elm_config->thumbscroll_friction;
+       if (dt > 1.0) dt = 1.0;
+       p = 1.0 - ((1.0 - dt) * (1.0 - dt));
+       dx = (sd->down.dx * _elm_config->thumbscroll_friction * p);
+       dy = (sd->down.dy * _elm_config->thumbscroll_friction * p);
+        sd->down.ax = dx;
+        sd->down.ay = dy;
+       x = sd->down.sx - dx;
+       y = sd->down.sy - dy;
+        hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &px, &py);
+        if ((sd->down.bounce_x_animator) ||
+            (sd->down.bounce_x_hold))
+          {
+             sd->down.bx = sd->down.bx0 - dx + sd->down.b0x;
+             x = px;
+          }
+        if ((sd->down.bounce_y_animator) ||
+            (sd->down.bounce_y_hold))
+          {
+             sd->down.by = sd->down.by0 - dy + sd->down.b0y;
+             y = py;
+          }
+       hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+       if (dt >= 1.0)
+         {
+             _smart_anim_stop(sd->smart_obj);
+            sd->down.momentum_animator = NULL;
+             sd->down.bounce_x_hold = 0;
+             sd->down.bounce_y_hold = 0;
+             sd->down.ax = 0;
+             sd->down.ay = 0;
+            return 0;
+         }
+     }
+   return 1;
+}
+
+static void
+bounce_eval(Hor_Smart_Data *sd)
+{
+   Evas_Coord mx, my, px, py, bx, by, b2x, b2y;
+
+   if (sd->freeze) return;
+   if ((!sd->bouncemex) && (!sd->bouncemey)) return;
+   if (sd->down.now) return; // down bounce while still held down
+   if (sd->down.onhold_animator)
+     {
+        ecore_animator_del(sd->down.onhold_animator);
+        sd->down.onhold_animator = NULL;
+     }
+   if (sd->down.hold_animator)
+     {
+        ecore_timer_del(sd->down.hold_animator);
+        sd->down.hold_animator = NULL;
+     }
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   bx = px;
+   by = py;
+   if (px < 0) px = 0;
+   if (px > mx) px = mx;
+   if (py < 0) py = 0;
+   if (py > my) py = my;
+   b2x = px;
+   b2y = py;
+   if (!sd->down.bounce_x_animator)
+     {
+        if (sd->bouncemex)
+          {
+             if (sd->scrollto.x.animator)
+               {
+                  ecore_animator_del(sd->scrollto.x.animator);
+                  sd->scrollto.x.animator = NULL;
+               }
+             sd->down.bounce_x_animator = ecore_animator_add(_smart_bounce_x_animator, sd);
+             sd->down.anim_start2 = ecore_loop_time_get();
+             sd->down.bx = bx;
+             sd->down.bx0 = bx;
+             sd->down.b2x = b2x;
+             if (sd->down.momentum_animator) sd->down.b0x = sd->down.ax;
+             else sd->down.b0x = 0;
+          }
+     }
+   if (!sd->down.bounce_y_animator)
+     {
+        if (sd->bouncemey)
+          {
+             if (sd->scrollto.y.animator)
+               {
+                  ecore_animator_del(sd->scrollto.y.animator);
+                  sd->scrollto.y.animator = NULL;
+               }
+             sd->down.bounce_y_animator = ecore_animator_add(_smart_bounce_y_animator, sd);
+             sd->down.anim_start3 = ecore_loop_time_get();
+             sd->down.by = by;
+             sd->down.by0 = by;
+             sd->down.b2y = b2y;
+             if (sd->down.momentum_animator) sd->down.b0y = sd->down.ay;
+             else sd->down.b0y = 0;
+          }
+     }
+}
+
+void
+hor_elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   Evas_Coord mx = 0, my = 0, px, py;
+   double vx, vy;
+
+   API_ENTRY return;
+   // FIXME: allow for bounce outside of range
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   if (mx > 0) vx = (double)x / (double)mx;
+   else vx = 0.0;
+   if (vx < 0.0) vx = 0.0;
+   else if (vx > 1.0) vx = 1.0;
+   if (my > 0) vy = (double)y / (double)my;
+   else vy = 0.0;
+   if (vy < 0.0) vy = 0.0;
+   else if (vy > 1.0) vy = 1.0;
+   edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, vy);
+   edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", vx, 0.0);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   if (!_elm_config->thumbscroll_bounce_enable)
+     {
+        if (x < 0) x = 0;
+        if (x > mx) x = mx;
+        if (y < 0) y = 0;
+        if (y > my) y = my;
+     }
+
+   if (!sd->bounce_horiz)
+     {
+        if (x < 0) x = 0;
+        if (x > mx) x = mx;
+     }
+   if (!sd->bounce_vert)
+     {
+        if (y < 0) y = 0;
+        if (y > my) y = my;
+     }
+
+   sd->pan_func.set(sd->pan_obj, x, y);
+   if ((px != x) || (py != y))
+     edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+   if (!sd->down.bounce_x_animator)
+     {
+        if ((x < 0) || (x > mx))
+          {
+             sd->bouncemex = 1;
+             bounce_eval(sd);
+          }
+     }
+   if (!sd->down.bounce_y_animator)
+     {
+        if ((y < 0) || (y > my))
+          {
+             sd->bouncemey = 1;
+             bounce_eval(sd);
+          }
+     }
+   if ((x != px) || (y != py))
+     {
+        evas_object_smart_callback_call(obj, "scroll", NULL);
+     }
+   if ((x != px)/* && (!sd->bouncemex)*/)
+     {
+        if (x == 0)
+          evas_object_smart_callback_call(obj, "edge,left", NULL);
+        if (x == mx)
+          evas_object_smart_callback_call(obj, "edge,right", NULL);
+     }
+   if ((y != py)/* && (!sd->bouncemey)*/)
+     {
+        if (y == 0)
+          evas_object_smart_callback_call(obj, "edge,top", NULL);
+        if (y == my)
+          evas_object_smart_callback_call(obj, "edge,bottom", NULL);
+     }
+}
+
+void
+hor_elm_smart_scroller_child_pos_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   API_ENTRY return;
+   sd->pan_func.get(sd->pan_obj, x, y);
+}
+
+void
+hor_elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   Evas_Coord mx = 0, my = 0, cw = 0, ch = 0, px = 0, py = 0, nx, ny;
+
+   API_ENTRY return;
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+
+   nx = px;
+   if (x < px) nx = x;
+   else if ((x + w) > (px + (cw - mx)))
+     {
+       nx = x + w - (cw - mx);
+       if (nx > x) nx = x;
+     }
+   ny = py;
+   if (y < py) ny = y;
+   else if ((y + h) > (py + (ch - my)))
+     {
+       ny = y + h - (ch - my);
+       if (ny > y) ny = y;
+     }
+   if ((nx == px) && (ny == py)) return;
+   if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
+       (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
+     {
+        _smart_anim_stop(sd->smart_obj);
+     }
+   if (sd->scrollto.x.animator)
+     {
+        ecore_animator_del(sd->scrollto.x.animator);
+        sd->scrollto.x.animator = NULL;
+     }
+   if (sd->scrollto.y.animator)
+     {
+        ecore_animator_del(sd->scrollto.y.animator);
+        sd->scrollto.y.animator = NULL;
+     }
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+        sd->bouncemex = 0;
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
+   if (sd->down.hold_animator)
+     {
+        ecore_timer_del(sd->down.hold_animator);
+        sd->down.hold_animator = NULL;
+        _smart_drag_stop(sd->smart_obj);
+     }
+   if (sd->down.momentum_animator)
+     {
+        ecore_animator_del(sd->down.momentum_animator);
+        sd->down.momentum_animator = NULL;
+        sd->down.bounce_x_hold = 0;
+        sd->down.bounce_y_hold = 0;
+        sd->down.ax = 0;
+        sd->down.ay = 0;
+     }
+   hor_elm_smart_scroller_child_pos_set(obj, nx, ny);
+}
+
+void
+hor_elm_smart_scroller_child_viewport_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
+{
+   API_ENTRY return;
+   edje_object_calc_force(sd->edje_obj);
+   evas_object_geometry_get(sd->pan_obj, NULL, NULL, w, h);
+}
+
+void
+hor_elm_smart_scroller_step_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   API_ENTRY return;
+   if (x < 1) x = 1;
+   if (y < 1) y = 1;
+   sd->step.x = x;
+   sd->step.y = y;
+   _smart_scrollbar_size_adjust(sd);
+}
+
+void
+hor_elm_smart_scroller_step_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   API_ENTRY return;
+   if (x) *x = sd->step.x;
+   if (y) *y = sd->step.y;
+}
+
+void
+hor_elm_smart_scroller_page_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   API_ENTRY return;
+   sd->page.x = x;
+   sd->page.y = y;
+   _smart_scrollbar_size_adjust(sd);
+}
+
+void
+hor_elm_smart_scroller_page_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
+{
+   API_ENTRY return;
+   if (x) *x = sd->page.x;
+   if (y) *y = sd->page.y;
+}
+
+void
+hor_elm_smart_scroller_policy_set(Evas_Object *obj, Elm_Very_Smart_Scroller_Policy hbar, Elm_Very_Smart_Scroller_Policy vbar)
+{
+   API_ENTRY return;
+   if ((sd->hbar_flags == hbar) && (sd->vbar_flags == vbar)) return;
+   sd->hbar_flags = hbar;
+   sd->vbar_flags = vbar;
+   if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
+   else if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
+   else
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,hbar", "elm");
+   if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_ON)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
+   else if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+     edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
+   else
+     edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm");
+   _smart_scrollbar_size_adjust(sd);
+}
+
+void
+hor_elm_smart_scroller_policy_get(Evas_Object *obj, Elm_Very_Smart_Scroller_Policy *hbar, Elm_Very_Smart_Scroller_Policy *vbar)
+{
+   API_ENTRY return;
+   if (hbar) *hbar = sd->hbar_flags;
+   if (vbar) *vbar = sd->vbar_flags;
+}
+
+Evas_Object *
+hor_elm_smart_scroller_edje_object_get(Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   return sd->edje_obj;
+}
+
+void
+hor_elm_smart_scroller_single_dir_set(Evas_Object *obj, Eina_Bool single_dir)
+{
+   API_ENTRY return;
+   sd->one_dir_at_a_time = single_dir;
+}
+
+Eina_Bool
+hor_elm_smart_scroller_single_dir_get(Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->one_dir_at_a_time;
+}
+
+void
+hor_elm_smart_scroller_theme_set(Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style)
+{
+   API_ENTRY return;
+   _elm_theme_object_set(parent, sd->edje_obj, clas, group, style);
+   if (sd->pan_obj)
+     edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
+   sd->vbar_visible = !sd->vbar_visible;
+   sd->hbar_visible = !sd->hbar_visible;
+   _smart_scrollbar_bar_visibility_adjust(sd);
+}
+
+void
+hor_elm_smart_scroller_hold_set(Evas_Object *obj, Eina_Bool hold)
+{
+   API_ENTRY return;
+   sd->hold = hold;
+}
+
+void
+hor_elm_smart_scroller_freeze_set(Evas_Object *obj, Eina_Bool freeze)
+{
+   API_ENTRY return;
+   sd->freeze = freeze;
+   if (sd->freeze)
+     {
+        if (sd->down.onhold_animator)
+          {
+             ecore_animator_del(sd->down.onhold_animator);
+             sd->down.onhold_animator = NULL;
+          }
+     }
+}
+
+void
+hor_elm_smart_scroller_bounce_allow_set(Evas_Object *obj, Eina_Bool horiz, Eina_Bool vert)
+{
+   API_ENTRY return;
+   sd->bounce_horiz = horiz;
+   sd->bounce_vert = vert;
+}
+
+void
+hor_elm_smart_scroller_paging_set(Evas_Object *obj, double pagerel_h, double pagerel_v, Evas_Coord pagesize_h, Evas_Coord pagesize_v)
+{
+   API_ENTRY return;
+   sd->pagerel_h = pagerel_h;
+   sd->pagerel_v = pagerel_v;
+   sd->pagesize_h = pagesize_h;
+   sd->pagesize_v = pagesize_v;
+   _smart_page_adjust(sd);
+}
+
+void
+hor_elm_smart_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+   Evas_Coord mx = 0, my = 0, cw = 0, ch = 0, px = 0, py = 0, nx, ny;
+
+   API_ENTRY return;
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+
+   nx = px;
+   if (x < px) nx = x;
+   else if ((x + w) > (px + (cw - mx)))
+     {
+       nx = x + w - (cw - mx);
+       if (nx > x) nx = x;
+     }
+   ny = py;
+   if (y < py) ny = y;
+   else if ((y + h) > (py + (ch - my)))
+     {
+       ny = y + h - (ch - my);
+       if (ny > y) ny = y;
+     }
+   if ((nx == px) && (ny == py)) return;
+   if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
+       (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
+     {
+        _smart_anim_stop(sd->smart_obj);
+     }
+   if (sd->scrollto.x.animator)
+     {
+        ecore_animator_del(sd->scrollto.x.animator);
+        sd->scrollto.x.animator = NULL;
+     }
+   if (sd->scrollto.y.animator)
+     {
+        ecore_animator_del(sd->scrollto.y.animator);
+        sd->scrollto.y.animator = NULL;
+     }
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+        sd->bouncemex = 0;
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
+   if (sd->down.hold_animator)
+     {
+        ecore_timer_del(sd->down.hold_animator);
+        sd->down.hold_animator = NULL;
+        _smart_drag_stop(sd->smart_obj);
+     }
+   if (sd->down.momentum_animator)
+     {
+        ecore_animator_del(sd->down.momentum_animator);
+        sd->down.momentum_animator = NULL;
+        sd->down.bounce_x_hold = 0;
+        sd->down.bounce_y_hold = 0;
+        sd->down.ax = 0;
+        sd->down.ay = 0;
+     }
+   x = nx;
+   if (x < 0) x = 0;
+   else if ((x + w) > cw) x = cw - w;
+   _smart_scrollto_x(sd, _elm_config->bring_in_scroll_friction, x);
+   y = ny;
+   if (y < 0) y = 0;
+   else if ((y + h) > ch) y = ch - h;
+   _smart_scrollto_y(sd, _elm_config->bring_in_scroll_friction, y);
+}
+
+/* local subsystem functions */
+static void
+_smart_edje_drag_v_start(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+   _smart_drag_start(sd->smart_obj);
+}
+
+static void
+_smart_edje_drag_v_stop(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+   _smart_drag_stop(sd->smart_obj);
+}
+
+static void
+_smart_edje_drag_v(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+}
+
+static void
+_smart_edje_drag_h_start(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+   _smart_drag_start(sd->smart_obj);
+}
+
+static void
+_smart_edje_drag_h_stop(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+   _smart_drag_stop(sd->smart_obj);
+}
+
+static void
+_smart_edje_drag_h(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   _smart_scrollbar_read(sd);
+}
+
+static void
+_smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   sd->child_obj = NULL;
+   _smart_scrollbar_size_adjust(sd);
+   _smart_scrollbar_reset(sd);
+}
+
+static void
+_smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info)
+{
+   Evas_Coord x, y;
+   Evas_Coord w, h;
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   sd->pan_func.get(sd->pan_obj, &x, &y);
+   sd->pan_func.child_size_get(sd->pan_obj, &w, &h);
+   if ((w != sd->child.w) || (h != sd->child.h))
+     {
+       sd->child.w = w;
+       sd->child.h = h;
+       _smart_scrollbar_size_adjust(sd);
+        evas_object_size_hint_min_set(sd->smart_obj, sd->child.w, sd->child.h);
+        hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+     }
+}
+
+static void
+_smart_pan_pan_changed_hook(void *data, Evas_Object *obj, void *event_info)
+{
+   Evas_Coord x, y;
+   Hor_Smart_Data *sd;
+
+   sd = data;
+   sd->pan_func.get(sd->pan_obj, &x, &y);
+   if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
+       (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
+     {
+        _smart_anim_stop(sd->smart_obj);
+     }
+   if (sd->scrollto.x.animator)
+     {
+        ecore_animator_del(sd->scrollto.x.animator);
+        sd->scrollto.x.animator = NULL;
+     }
+   if (sd->scrollto.y.animator)
+     {
+        ecore_animator_del(sd->scrollto.y.animator);
+        sd->scrollto.y.animator = NULL;
+     }
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+        sd->bouncemex = 0;
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
+   hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+}
+
+static void
+_smart_event_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Wheel *ev;
+   Hor_Smart_Data *sd;
+   Evas_Coord x = 0, y = 0;
+
+   sd = data;
+   ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
+   if (evas_key_modifier_is_set(ev->modifiers, "Control") ||
+       evas_key_modifier_is_set(ev->modifiers, "Alt") ||
+       evas_key_modifier_is_set(ev->modifiers, "Shift") ||
+       evas_key_modifier_is_set(ev->modifiers, "Meta") ||
+       evas_key_modifier_is_set(ev->modifiers, "Hyper") ||
+       evas_key_modifier_is_set(ev->modifiers, "Super"))
+     return;
+   hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
+       (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
+     {
+        _smart_anim_stop(sd->smart_obj);
+     }
+   if (sd->scrollto.x.animator)
+     {
+        ecore_animator_del(sd->scrollto.x.animator);
+        sd->scrollto.x.animator = NULL;
+     }
+   if (sd->scrollto.y.animator)
+     {
+        ecore_animator_del(sd->scrollto.y.animator);
+        sd->scrollto.y.animator = NULL;
+     }
+   if (sd->down.bounce_x_animator)
+     {
+        ecore_animator_del(sd->down.bounce_x_animator);
+        sd->down.bounce_x_animator = NULL;
+        sd->bouncemex = 0;
+     }
+   if (sd->down.bounce_y_animator)
+     {
+        ecore_animator_del(sd->down.bounce_y_animator);
+        sd->down.bounce_y_animator = NULL;
+        sd->bouncemey = 0;
+     }
+   if (ev->direction == 0)
+     y += ev->z * sd->step.y;
+   else if (ev->direction == 1)
+     x += ev->z * sd->step.x;
+   hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+}
+
+static void
+_smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev;
+   Hor_Smart_Data *sd;
+   Evas_Coord x = 0, y = 0;
+
+   sd = data;
+   ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
+   if (_elm_config->thumbscroll_enable)
+     {
+        if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
+            (sd->down.momentum_animator) || (sd->scrollto.x.animator) ||
+            (sd->scrollto.y.animator))
+          {
+             _smart_anim_stop(sd->smart_obj);
+          }
+        if (sd->scrollto.x.animator)
+          {
+             ecore_animator_del(sd->scrollto.x.animator);
+             sd->scrollto.x.animator = NULL;
+          }
+        if (sd->scrollto.y.animator)
+          {
+             ecore_animator_del(sd->scrollto.y.animator);
+             sd->scrollto.y.animator = NULL;
+          }
+        if (sd->down.bounce_x_animator)
+          {
+             ecore_animator_del(sd->down.bounce_x_animator);
+             sd->down.bounce_x_animator = NULL;
+             sd->bouncemex = 0;
+          }
+        if (sd->down.bounce_y_animator)
+          {
+             ecore_animator_del(sd->down.bounce_y_animator);
+             sd->down.bounce_y_animator = NULL;
+             sd->bouncemey = 0;
+          }
+       if (sd->down.hold_animator)
+         {
+            ecore_timer_del(sd->down.hold_animator);
+            sd->down.hold_animator = NULL;
+             _smart_drag_stop(sd->smart_obj);
+         }
+       if (sd->down.momentum_animator)
+         {
+            ecore_animator_del(sd->down.momentum_animator);
+            sd->down.momentum_animator = NULL;
+             sd->down.bounce_x_hold = 0;
+             sd->down.bounce_y_hold = 0;
+             sd->down.ax = 0;
+             sd->down.ay = 0;
+         }
+       if (ev->button == 1)
+         {
+            sd->down.now = 1;
+            sd->down.dragged = 0;
+            sd->down.dir_x = 0;
+            sd->down.dir_y = 0;
+            sd->down.dir_none = 0;
+            sd->down.x = ev->canvas.x;
+            sd->down.y = ev->canvas.y;
+            hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+            sd->down.sx = x;
+            sd->down.sy = y;
+            sd->down.locked = 0;
+            memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 20);
+#ifdef EVTIME
+            sd->down.history[0].timestamp = ev->timestamp / 1000.0;
+#else
+            sd->down.history[0].timestamp = ecore_loop_time_get();
+#endif
+            sd->down.history[0].x = ev->canvas.x;
+            sd->down.history[0].y = ev->canvas.y;
+
+#ifdef SMART_SCROLLER
+
+               int i;
+               if(sd->timer) {
+                       ecore_timer_del(sd->timer);
+                       sd->timer = NULL;
+               }
+               if(sd->special_timer) {
+                       ecore_timer_del(sd->special_timer);
+                       sd->special_timer = NULL;
+               }
+               
+               for ( i =0; i < EVENT_Q_MAX; i++)
+                       sd->event_queue[i] = 0;
+
+               sd->producer = 0;
+               sd->resaler = 0;
+               sd->consumer = 0;
+               sd->special_prev_x = sd->special_cur_x = ev->canvas.x;
+               sd->resaler_continue = 1;       
+               sd->move_cnt = 0;
+               sd->x_pos = x * -1;
+
+#endif
+         }
+     }
+}
+
+static Eina_Bool
+_smart_hold_animator(void *data)
+{
+   Hor_Smart_Data *sd = data;
+   hor_elm_smart_scroller_child_pos_set(sd->smart_obj, sd->down.hold_x, sd->down.hold_y);
+   return 1;
+}
+
+static void
+_smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Down *ev;
+   Hor_Smart_Data *sd;
+   Evas_Coord x = 0, y = 0, ox = 0, oy = 0;
+
+   sd = data;
+   ev = event_info;
+
+               #ifdef SMART_SCROLLER
+       sd->resaler_continue = 0;
+               if (sd->freeze) sd->hold = 0;
+
+#endif
+
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
+   // FIXME: respect elm_widget_scroll_hold_get of parent container
+   if (_elm_config->thumbscroll_enable)
+     {
+       if (ev->button == 1)
+         {
+
+
+
+             if (sd->down.onhold_animator)
+               {
+                  ecore_animator_del(sd->down.onhold_animator);
+                  sd->down.onhold_animator = NULL;
+               }
+            x = ev->canvas.x - sd->down.x;
+            y = ev->canvas.y - sd->down.y;
+             if (sd->down.dragged)
+               {
+                  _smart_drag_stop(sd->smart_obj);
+                  if ((!sd->hold) && (!sd->freeze))
+                    {
+                       double t, at, dt;
+                       int i;
+                       Evas_Coord ax, ay, dx, dy, vel;
+
+#ifdef EVTIME
+                       t = ev->timestamp / 1000.0;
+#else
+                       t = ecore_loop_time_get();
+#endif
+                       ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+                       ax = ev->canvas.x;
+                       ay = ev->canvas.y;
+                       at = 0.0;
+#ifdef SCROLLDBG
+                       printf("------ %i %i\n", ev->canvas.x, ev->canvas.y);
+#endif
+                       for (i = 0; i < 20; i++)
+                         {
+                            dt = t - sd->down.history[i].timestamp;
+                            if (dt > 0.2) break;
+#ifdef SCROLLDBG
+                            printf("H: %i %i @ %1.3f\n",
+                                   sd->down.history[i].x,
+                                   sd->down.history[i].y, dt);
+#endif
+                            at += dt;
+                            ax += sd->down.history[i].x;
+                            ay += sd->down.history[i].y;
+                         }
+                       ax /= (i + 1);
+                       ay /= (i + 1);
+                       at /= (i + 1);
+                       at *= 4.0;
+                       dx = ev->canvas.x - ax;
+                       dy = ev->canvas.y - ay;
+                       if (at > 0)
+                         {
+                            vel = sqrt((dx * dx) + (dy * dy)) / at;
+                            if ((_elm_config->thumbscroll_friction > 0.0) &&
+                                (vel > _elm_config->thumbscroll_momentum_threshhold) &&
+                                (!sd->freeze))
+                              {
+                                 sd->down.dx = ((double)dx / at);
+                                 sd->down.dy = ((double)dy / at);
+                                 ox = -sd->down.dx;
+                                 oy = -sd->down.dy;
+                                 if (!_smart_do_page(sd))
+                                   {
+                                      if (!sd->down.momentum_animator)
+                                        {
+                                           sd->down.momentum_animator = ecore_animator_add(_smart_momentum_animator, sd);
+                                           _smart_anim_start(sd->smart_obj);
+                                        }
+                                      sd->down.anim_start = ecore_loop_time_get();
+                                      hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+                                      sd->down.sx = x;
+                                      sd->down.sy = y;
+                                      sd->down.b0x = 0;
+                                      sd->down.b0y = 0;
+                                   }
+                              }
+                                          }
+                                          
+                       if (sd->down.hold_animator)
+                         {
+                            ecore_timer_del(sd->down.hold_animator);
+                            sd->down.hold_animator = NULL;
+                         }
+                    }
+                  evas_event_feed_hold(e, 0, ev->timestamp, ev->data);
+                  if (_smart_do_page(sd))
+                    {
+                       Evas_Coord pgx, pgy;
+
+                       hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+                       pgx = _smart_page_x_get(sd, ox);
+                                          // HERE::modify pgx for moving one page
+                       //if (pgx != x) _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
+                       _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
+                       pgy = _smart_page_y_get(sd, oy);
+                       if (pgy != y) _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
+                       //_smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
+                    }
+              }
+             else
+               {
+                  if (_smart_do_page(sd))
+                    {
+                       Evas_Coord pgx, pgy;
+
+                       hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+                       pgx = _smart_page_x_get(sd, ox);
+                       if (pgx != x) _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
+                       pgy = _smart_page_y_get(sd, oy);
+                       if (pgy != y) _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
+                    }
+               }
+            sd->down.dragged = 0;
+            sd->down.now = 0;
+             hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+             hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+             if (!_smart_do_page(sd))
+               bounce_eval(sd);
+         }
+     }
+}
+
+static Eina_Bool
+_smart_onhold_animator(void *data)
+{
+   Hor_Smart_Data *sd;
+   double t, td;
+   double vx, vy;
+   Evas_Coord x, y, ox, oy; 
+
+   sd = data;
+   t = ecore_loop_time_get();
+   if (sd->down.onhold_tlast > 0.0)
+     {
+        td = t - sd->down.onhold_tlast;
+        vx = sd->down.onhold_vx * td * (double)_elm_config->thumbscroll_threshhold * 2.0;
+        vy = sd->down.onhold_vy * td * (double)_elm_config->thumbscroll_threshhold * 2.0;
+        hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
+        sd->down.onhold_vxe += vx;
+        sd->down.onhold_vye += vy;
+        x = ox + (int)sd->down.onhold_vxe;
+        y = oy + (int)sd->down.onhold_vye;
+        sd->down.onhold_vxe -= (int)sd->down.onhold_vxe;
+        sd->down.onhold_vye -= (int)sd->down.onhold_vye;
+        hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+//        printf("scroll %i %i\n", sd->down.hold_x, sd->down.hold_y);
+     }
+   sd->down.onhold_tlast = t;
+   return 1;
+}
+
+#ifdef SMART_SCROLLER
+static int 
+get_average(void *d)
+{
+       Hor_Smart_Data *sd = d;
+       int number = 0;
+       int key = 0;
+       int sum = 0;
+       int weight = 0;
+       int number_square;
+       int sum_of_weight = 0;
+       register int i = 1;
+
+//     if (getenv(NUMBERS_OF_AVERAGE_QUEUE))
+//             number = atoi(getenv(NUMBERS_OF_AVERAGE_QUEUE));
+//     else return false;
+       number = NUMBERS_OF_AVERAGE_QUEUE;
+       number_square = number * number * number;
+
+       // i <= number : origin, but i'll try to process cur_x-prev_x in consumer_timer
+       // FIXME
+       for (i = 1; i <= number; i++)
+       {
+               if ((key = sd->producer-i) < 0) key = EVENT_Q_MAX + key;
+                       weight = (number_square  /  (i*i*i)) + 1;
+               
+               sum += sd->event_queue[key] * weight;
+               sum_of_weight += weight;
+       }
+       sd->consumer_queue[sd->resaler] = (int) sum / sum_of_weight;
+       sd->resaler = (sd->resaler+1) % EVENT_Q_MAX;
+
+       return 1;
+}
+
+
+static Eina_Bool special_timer_cb(void *d)
+{
+       Hor_Smart_Data *sd = d;
+
+       sd->special_prev_x = sd->special_cur_x;
+       sd->special_cur_x = sd->cur_x;
+       sd->event_queue[sd->producer] = sd->special_cur_x - sd->special_prev_x;
+       sd->producer = ((sd->producer + 1) % EVENT_Q_MAX);
+
+       if (sd->resaler_continue) if (!get_average(sd)) return ECORE_CALLBACK_RENEW;
+
+       if (sd->resaler == sd->consumer) {
+               sd->done = 1;
+               sd->special_timer = NULL;
+               return ECORE_CALLBACK_CANCEL;
+       }
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool consumer_timer_cb(void *d)
+{
+       Hor_Smart_Data *sd = d;
+       int tmp_movement = 0;
+
+// TODO: OPTIMIZE ME
+       tmp_movement = sd->consumer_queue[sd->consumer-1];
+
+       sd->x_pos += tmp_movement;
+       hor_elm_smart_scroller_child_pos_set(sd->smart_obj, sd->x_pos * -1, sd->down.hold_y);
+         
+       //if (sd->resaler == sd->consumer) {
+       if (sd->done == 1) {
+               sd->done = 0;
+               sd->timer = NULL;
+               memset(sd->event_queue, 0x00, EVENT_Q_MAX);
+               return ECORE_CALLBACK_CANCEL;
+       }
+       sd->consumer = (sd->consumer + 1) % EVENT_Q_MAX;
+
+       return ECORE_CALLBACK_RENEW;
+}
+#endif
+
+static void
+_smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Mouse_Move *ev;
+   Hor_Smart_Data *sd;
+   Evas_Coord x = 0, y = 0;
+
+   sd = data;
+   ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
+   // FIXME: respect elm_widget_scroll_hold_get of parent container
+   if (_elm_config->thumbscroll_enable)
+     {
+       if (sd->down.now)
+         {
+             int faildir = 0;
+
+#ifdef SCROLLDBG
+             printf("::: %i %i\n", ev->cur.canvas.x, ev->cur.canvas.y);
+#endif
+            memmove(&(sd->down.history[1]), &(sd->down.history[0]),
+                    sizeof(sd->down.history[0]) * 19);
+#ifdef EVTIME
+            sd->down.history[0].timestamp = ev->timestamp / 1000.0;
+#else
+            sd->down.history[0].timestamp = ecore_loop_time_get();
+#endif
+            sd->down.history[0].x = ev->cur.canvas.x;
+            sd->down.history[0].y = ev->cur.canvas.y;
+
+            x = ev->cur.canvas.x - sd->down.x;
+            if (x < 0) x = -x;      y = ev->cur.canvas.y - sd->down.y;
+            if (y < 0) y = -y;
+
+#if 0
+#ifdef SMART_SCROLLER
+               sd->cur_x = ev->cur.canvas.x;
+               sd->prev_x = ev->prev.canvas.x;
+               sd->move_cnt++;
+
+               if (!sd->special_timer)
+               {
+
+                       sd->special_timer = ecore_timer_add(1.0f / NR_OF_FRAMES, special_timer_cb, data);
+               }
+
+               if (!sd->timer)
+               {
+                       sd->timer = ecore_timer_add(1.0f / NR_OF_FRAMES, consumer_timer_cb, data);
+               }
+
+#endif
+#endif
+               
+                
+            if ((sd->one_dir_at_a_time) &&
+                (!sd->down.dir_x) && (!sd->down.dir_y) && (!sd->down.dir_none))
+              {
+                  if (x > _elm_config->thumbscroll_threshhold)
+                    {
+                       if (x > (y * 2))
+                         {
+                           sd->down.dir_x = 1;
+                           sd->down.dir_y = 0;
+                        }
+                       else faildir++;
+                   }
+                  if (y > _elm_config->thumbscroll_threshhold)
+                   {
+                       if (y > (x * 2))
+                        {
+                           sd->down.dir_x = 0;
+                           sd->down.dir_y = 1;
+                         }
+                       else faildir++;
+                   }
+                  if (faildir) sd->down.dir_none = 1;
+              }
+           if ((!sd->hold) && (!sd->freeze))
+               {
+#ifdef SMART_SCROLLER
+               sd->cur_x = ev->cur.canvas.x;
+               sd->prev_x = ev->prev.canvas.x;
+               sd->move_cnt++;
+
+               if (!sd->special_timer)
+               {
+
+                       sd->special_timer = ecore_timer_add(1.0f / NR_OF_FRAMES, special_timer_cb, data);
+               }
+
+               if (!sd->timer)
+               {
+                       sd->timer = ecore_timer_add(1.0f / NR_OF_FRAMES, consumer_timer_cb, data);
+               }
+#endif
+
+
+                  if ((sd->down.dragged) ||
+                      (((x * x) + (y * y)) >
+                       (_elm_config->thumbscroll_threshhold *
+                        _elm_config->thumbscroll_threshhold)) )
+                                         //|| x < SMART_MOVE_THRESHOLD)
+                    {
+                       if (!sd->down.dragged)
+                         {
+                            evas_event_feed_hold(e, 1, ev->timestamp, ev->data);
+                            _smart_drag_start(sd->smart_obj);
+                         }
+                       ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+                       sd->down.dragged = 1;
+                       x = sd->down.sx - (ev->cur.canvas.x - sd->down.x);
+                       y = sd->down.sy - (ev->cur.canvas.y - sd->down.y);
+                       if ((sd->down.dir_x) || (sd->down.dir_y))
+                         {
+                            if (!sd->down.locked)
+                              {
+                                 sd->down.locked_x = x;
+                                 sd->down.locked_y = y;
+                                 sd->down.locked = 1;
+                              }
+                            if (sd->down.dir_x) y = sd->down.locked_y;
+                            else x = sd->down.locked_x;
+                         }
+                       sd->down.hold_x = x;
+                       sd->down.hold_y = y;
+#ifndef SMART_SCROLLER
+                       if (!sd->down.hold_animator)
+                         {
+                            sd->down.hold_animator = ecore_timer_add(1.0f / 60.0f,_smart_hold_animator, sd);
+                         }
+#endif
+//                       printf("a %i %i\n", sd->down.hold_x, sd->down.hold_y);
+//                       _smart_onhold_animator(sd);
+//                       hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+                    }
+              }
+             else if (!sd->freeze)
+               {
+                  Evas_Coord ex, ey, ew, eh;
+                  double vx = 0.0, vy = 0.0;
+
+
+                  evas_object_geometry_get(sd->event_obj, &ex, &ey, &ew, &eh);
+                  x = ev->cur.canvas.x - ex;
+                  y = ev->cur.canvas.y - ey;
+                  if (x < _elm_config->thumbscroll_threshhold)
+                    {
+                       if (_elm_config->thumbscroll_threshhold > 0.0)
+                         vx = -(double)(_elm_config->thumbscroll_threshhold - x) /
+                         _elm_config->thumbscroll_threshhold;
+                       else
+                         vx = -1.0;
+                    }
+                  else if (x > (ew - _elm_config->thumbscroll_threshhold))
+                    {
+                       if (_elm_config->thumbscroll_threshhold > 0.0)
+                         vx = (double)(_elm_config->thumbscroll_threshhold - (ew - x)) /
+                         _elm_config->thumbscroll_threshhold;
+                       else
+                         vx = 1.0;
+                    }
+                  if (y < _elm_config->thumbscroll_threshhold)
+                    {
+                       if (_elm_config->thumbscroll_threshhold > 0.0)
+                         vy = -(double)(_elm_config->thumbscroll_threshhold - y) /
+                         _elm_config->thumbscroll_threshhold;
+                       else
+                         vy = -1.0;
+                    }
+                  else if (y > (eh - _elm_config->thumbscroll_threshhold))
+                    {
+                       if (_elm_config->thumbscroll_threshhold > 0.0)
+                         vy = (double)(_elm_config->thumbscroll_threshhold - (eh - y)) /
+                         _elm_config->thumbscroll_threshhold;
+                       else
+                         vy = 1.0;
+                    }
+                  if ((vx != 0.0) || (vy != 0.0))
+                    {
+                       sd->down.onhold_vx = vx;
+                       sd->down.onhold_vy = vy;
+                       if (!sd->down.onhold_animator)
+                         {
+                            sd->down.onhold_vxe = 0.0;
+                            sd->down.onhold_vye = 0.0;
+                            sd->down.onhold_tlast = 0.0;
+                            sd->down.onhold_animator = ecore_animator_add(_smart_onhold_animator, sd);
+                         }
+//                       printf("b %i %i\n", sd->down.hold_x, sd->down.hold_y);
+                    }
+                  else
+                    {
+                       if (sd->down.onhold_animator)
+                         {
+                            ecore_animator_del(sd->down.onhold_animator);
+                               //ecore_timer_del(sd->down.onhold_animator);
+                            sd->down.onhold_animator = NULL;
+                         }
+                    }
+               }
+                          else if (sd->freeze)
+                          {
+                                       if(sd->timer) {
+                                               ecore_timer_del(sd->timer);
+                                               sd->timer = NULL;
+                                       }
+                                       if(sd->special_timer) {
+                                               ecore_timer_del(sd->special_timer);
+                                               sd->special_timer = NULL;
+                                       }
+                          }
+         }
+         
+     }
+}
+
+static void
+_smart_event_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+   Evas_Event_Key_Down *ev;
+   Hor_Smart_Data *sd;
+   Evas_Coord x = 0, y = 0, vw = 0, vh = 0, mx = 0, my = 0;
+   int xch = 0, ych = 0;
+
+   sd = data;
+   ev = event_info;
+   if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
+   hor_elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
+   if (!strcmp(ev->keyname, "Left"))
+     {
+        x -= sd->step.x;
+        xch = 1;
+     }
+   else if (!strcmp(ev->keyname, "Right"))
+     {
+        x += sd->step.x;
+        xch = 1;
+     }
+   else if (!strcmp(ev->keyname, "Up"))
+     {
+        y -= sd->step.y;
+        ych = 1;
+     }
+   else if (!strcmp(ev->keyname, "Home"))
+     {
+        y = 0;
+        ych = 1;
+     }
+   else if (!strcmp(ev->keyname, "End"))
+     {
+        y = my;
+        ych = 1;
+     }
+   else if (!strcmp(ev->keyname, "Down"))
+     {
+        y += sd->step.y;
+        ych = 1;
+     }
+   else if (!strcmp(ev->keyname, "Prior"))
+     {
+       if (sd->page.y < 0)
+         y -= -(sd->page.y * vh) / 100;
+       else
+         y -= sd->page.y;
+        ych = 1;
+     }
+   else if (!strcmp(ev->keyname, "Next"))
+     {
+       if (sd->page.y < 0)
+         y += -(sd->page.y * vh) / 100;
+       else
+         y += sd->page.y;
+        ych = 1;
+     }
+   if (xch)
+     {
+        if (sd->scrollto.x.animator)
+          {
+             ecore_animator_del(sd->scrollto.x.animator);
+             sd->scrollto.x.animator = NULL;
+          }
+        if (sd->down.bounce_x_animator)
+          {
+             ecore_animator_del(sd->down.bounce_x_animator);
+             sd->down.bounce_x_animator = NULL;
+             sd->bouncemex = 0;
+          }
+     }
+   if (ych)
+     {
+        if (sd->scrollto.y.animator)
+          {
+             ecore_animator_del(sd->scrollto.y.animator);
+             sd->scrollto.y.animator = NULL;
+          }
+        if (sd->down.bounce_y_animator)
+          {
+             ecore_animator_del(sd->down.bounce_y_animator);
+             sd->down.bounce_y_animator = NULL;
+             sd->bouncemey = 0;
+          }
+     }
+
+   hor_elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
+}
+
+static void
+_smart_scrollbar_read(Hor_Smart_Data *sd)
+{
+   Evas_Coord x, y, mx = 0, my = 0, px, py;
+   double vx, vy;
+
+   edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
+   edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
+   sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+   x = vx * (double)mx;
+   y = vy * (double)my;
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   sd->pan_func.set(sd->pan_obj, x, y);
+   if ((px != x) || (py != y))
+     edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+}
+
+static void
+_smart_scrollbar_reset(Hor_Smart_Data *sd)
+{
+   Evas_Coord px = 0, py = 0;
+
+   edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
+   edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
+   if ((!sd->child_obj) && (!sd->extern_pan))
+     {
+       edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
+       edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
+     }
+   sd->pan_func.get(sd->pan_obj, &px, &py);
+   sd->pan_func.set(sd->pan_obj, 0, 0);
+   if ((px != 0) || (py != 0))
+     edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+}
+
+static int
+_smart_scrollbar_bar_v_visibility_adjust(Hor_Smart_Data *sd)
+{
+   int scroll_v_vis_change = 0;
+   Evas_Coord w, h, vw, vh;
+
+   w = sd->child.w;
+   h = sd->child.h;
+   evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
+   if (sd->vbar_visible)
+     {
+       if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_AUTO)
+         {
+            if ((sd->child_obj) || (sd->extern_pan))
+              {
+                 if (h <= vh)
+                   {
+                      scroll_v_vis_change = 1;
+                      sd->vbar_visible = 0;
+                   }
+              }
+            else
+              {
+                 scroll_v_vis_change = 1;
+                 sd->vbar_visible = 0;
+              }
+         }
+       else if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+         {
+            scroll_v_vis_change = 1;
+            sd->vbar_visible = 0;
+         }
+     }
+   else
+     {
+       if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_AUTO)
+         {
+            if ((sd->child_obj) || (sd->extern_pan))
+              {
+                 if (h > vh)
+                   {
+                      scroll_v_vis_change = 1;
+                      sd->vbar_visible = 1;
+                   }
+              }
+         }
+       else if (sd->vbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_ON)
+         {
+            scroll_v_vis_change = 1;
+            sd->vbar_visible = 1;
+         }
+     }
+   if (scroll_v_vis_change)
+     {
+        if (sd->vbar_flags != ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+          {
+             if (sd->vbar_visible)
+               edje_object_signal_emit(sd->edje_obj, "elm,action,show,vbar", "elm");
+             else
+               edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
+             edje_object_message_signal_process(sd->edje_obj);
+             _smart_scrollbar_size_adjust(sd);
+          }
+        else
+          edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
+     }
+   return scroll_v_vis_change;
+}
+
+static int
+_smart_scrollbar_bar_h_visibility_adjust(Hor_Smart_Data *sd)
+{
+   int scroll_h_vis_change = 0;
+   Evas_Coord w, h, vw, vh;
+
+   w = sd->child.w;
+   h = sd->child.h;
+   evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
+   if (sd->hbar_visible)
+     {
+       if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_AUTO)
+         {
+            if ((sd->child_obj) || (sd->extern_pan))
+              {
+                 if (w <= vw)
+                   {
+                      scroll_h_vis_change = 1;
+                      sd->hbar_visible = 0;
+                   }
+              }
+            else
+              {
+                 scroll_h_vis_change = 1;
+                 sd->hbar_visible = 0;
+              }
+         }
+       else if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+         {
+            scroll_h_vis_change = 1;
+            sd->hbar_visible = 0;
+         }
+     }
+   else
+     {
+       if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_AUTO)
+         {
+            if ((sd->child_obj) || (sd->extern_pan))
+              {
+                 if (w > vw)
+                   {
+                      scroll_h_vis_change = 1;
+                      sd->hbar_visible = 1;
+                   }
+              }
+         }
+       else if (sd->hbar_flags == ELM_VERY_SMART_SCROLLER_POLICY_ON)
+         {
+            scroll_h_vis_change = 1;
+            sd->hbar_visible = 1;
+         }
+     }
+   if (scroll_h_vis_change)
+     {
+        if (sd->hbar_flags != ELM_VERY_SMART_SCROLLER_POLICY_OFF)
+          {
+             if (sd->hbar_visible)
+               edje_object_signal_emit(sd->edje_obj, "elm,action,show,hbar", "elm");
+             else
+               edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
+             edje_object_message_signal_process(sd->edje_obj);
+             _smart_scrollbar_size_adjust(sd);
+          }
+        else
+          edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
+       _smart_scrollbar_size_adjust(sd);
+     }
+   return scroll_h_vis_change;
+}
+
+static void
+_smart_scrollbar_bar_visibility_adjust(Hor_Smart_Data *sd)
+{
+   int changed = 0;
+
+   changed |= _smart_scrollbar_bar_h_visibility_adjust(sd);
+   changed |= _smart_scrollbar_bar_v_visibility_adjust(sd);
+   if (changed)
+     {
+       _smart_scrollbar_bar_h_visibility_adjust(sd);
+       _smart_scrollbar_bar_v_visibility_adjust(sd);
+     }
+}
+
+static void
+_smart_scrollbar_size_adjust(Hor_Smart_Data *sd)
+{
+   if ((sd->child_obj) || (sd->extern_pan))
+     {
+       Evas_Coord x, y, w, h, mx = 0, my = 0, vw = 0, vh = 0, px, py;
+       double vx, vy, size;
+
+       edje_object_part_geometry_get(sd->edje_obj, "elm.swallow.content",
+                                     NULL, NULL, &vw, &vh);
+       w = sd->child.w;
+       if (w < 1) w = 1;
+       size = (double)vw / (double)w;
+       if (size > 1.0)
+         {
+            size = 1.0;
+            edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
+         }
+       edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", size, 1.0);
+
+       h = sd->child.h;
+       if (h < 1) h = 1;
+       size = (double)vh / (double)h;
+       if (size > 1.0)
+         {
+            size = 1.0;
+            edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
+         }
+       edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, size);
+
+       edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
+       edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
+       sd->pan_func.max_get(sd->pan_obj, &mx, &my);
+       x = vx * mx;
+       y = vy * my;
+
+       edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->step.x / (double)w, 0.0);
+       edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->step.y / (double)h);
+       if (sd->page.x > 0)
+         edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->page.x / (double)w, 0.0);
+       else
+         edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", -((double)sd->page.x * ((double)vw / (double)w)) / 100.0, 0.0);
+       if (sd->page.y > 0)
+         edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->page.y / (double)h);
+       else
+         edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, -((double)sd->page.y * ((double)vh / (double)h)) / 100.0);
+
+       sd->pan_func.get(sd->pan_obj, &px, &py);
+        if (vx != mx) x = px;
+        if (vy != my) y = py;
+       sd->pan_func.set(sd->pan_obj, x, y);
+//     if ((px != 0) || (py != 0))
+//       edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+     }
+   else
+     {
+       Evas_Coord px = 0, py = 0;
+
+       edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
+       edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
+       sd->pan_func.get(sd->pan_obj, &px, &py);
+       sd->pan_func.set(sd->pan_obj, 0, 0);
+       if ((px != 0) || (py != 0))
+         edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
+     }
+   _smart_scrollbar_bar_visibility_adjust(sd);
+}
+
+static void
+_smart_reconfigure(Hor_Smart_Data *sd)
+{
+   evas_object_move(sd->edje_obj, sd->x, sd->y);
+   evas_object_resize(sd->edje_obj, sd->w, sd->h);
+   evas_object_move(sd->event_obj, sd->x, sd->y);
+   evas_object_resize(sd->event_obj, sd->w, sd->h);
+   _smart_scrollbar_size_adjust(sd);
+}
+
+static void
+_smart_add(Evas_Object *obj)
+{
+   Hor_Smart_Data *sd;
+   Evas_Object *o;
+
+   sd = calloc(1, sizeof(Hor_Smart_Data));
+   if (!sd) return;
+   evas_object_smart_data_set(obj, sd);
+
+   sd->smart_obj = obj;
+   sd->x = 0;
+   sd->y = 0;
+   sd->w = 0;
+   sd->h = 0;
+   sd->step.x = 32;
+   sd->step.y = 32;
+   sd->page.x = -50;
+   sd->page.y = -50;
+   sd->hbar_flags = ELM_VERY_SMART_SCROLLER_POLICY_AUTO;
+   sd->vbar_flags = ELM_VERY_SMART_SCROLLER_POLICY_AUTO;
+   sd->hbar_visible = 1;
+   sd->vbar_visible = 1;
+
+   sd->bounce_horiz = 1;
+   sd->bounce_vert = 1;
+
+   sd->one_dir_at_a_time = 1;
+
+   evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _smart_event_key_down, sd);
+   evas_object_propagate_events_set(obj, 0);
+
+   o = edje_object_add(evas_object_evas_get(obj));
+   sd->edje_obj = o;
+   _elm_theme_object_set(NULL, o, "scroller", "base", "default");
+   edje_object_signal_callback_add(o, "drag", "elm.dragable.vbar", _smart_edje_drag_v, sd);
+   edje_object_signal_callback_add(o, "drag,start", "elm.dragable.vbar", _smart_edje_drag_v_start, sd);
+   edje_object_signal_callback_add(o, "drag,stop", "elm.dragable.vbar", _smart_edje_drag_v_stop, sd);
+   edje_object_signal_callback_add(o, "drag,step", "elm.dragable.vbar", _smart_edje_drag_v, sd);
+   edje_object_signal_callback_add(o, "drag,page", "elm.dragable.vbar", _smart_edje_drag_v, sd);
+   edje_object_signal_callback_add(o, "drag", "elm.dragable.hbar", _smart_edje_drag_h, sd);
+   edje_object_signal_callback_add(o, "drag,start", "elm.dragable.hbar", _smart_edje_drag_h_start, sd);
+   edje_object_signal_callback_add(o, "drag,stop", "elm.dragable.hbar", _smart_edje_drag_h_stop, sd);
+   edje_object_signal_callback_add(o, "drag,step", "elm.dragable.hbar", _smart_edje_drag_h, sd);
+   edje_object_signal_callback_add(o, "drag,page", "elm.dragable.hbar", _smart_edje_drag_h, sd);
+   evas_object_smart_member_add(o, obj);
+
+   o = evas_object_rectangle_add(evas_object_evas_get(obj));
+   sd->event_obj = o;
+   evas_object_color_set(o, 0, 0, 0, 0);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _smart_event_mouse_down, sd);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _smart_event_mouse_up, sd);
+   evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _smart_event_mouse_move, sd);
+   evas_object_smart_member_add(o, obj);
+   evas_object_repeat_events_set(o, 1);
+
+   sd->pan_func.set = _elm_smart_pan_set;
+   sd->pan_func.get = _elm_smart_pan_get;
+   sd->pan_func.max_get = _elm_smart_pan_max_get;
+   sd->pan_func.child_size_get = _elm_smart_pan_child_size_get;
+
+   _smart_scrollbar_reset(sd);
+}
+
+static void
+_smart_del(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   hor_elm_smart_scroller_child_set(obj, NULL);
+   if (!sd->extern_pan) evas_object_del(sd->pan_obj);
+   evas_object_del(sd->edje_obj);
+   evas_object_del(sd->event_obj);
+   if (sd->down.hold_animator) ecore_timer_del(sd->down.hold_animator);
+   if (sd->down.onhold_animator) ecore_animator_del(sd->down.onhold_animator);
+   if (sd->down.momentum_animator) ecore_animator_del(sd->down.momentum_animator);
+   if (sd->down.bounce_x_animator) ecore_animator_del(sd->down.bounce_x_animator);
+   if (sd->down.bounce_y_animator) ecore_animator_del(sd->down.bounce_y_animator);
+   if (sd->scrollto.x.animator) ecore_animator_del(sd->scrollto.x.animator);
+   if (sd->scrollto.y.animator) ecore_animator_del(sd->scrollto.y.animator);
+   free(sd);
+   evas_object_smart_data_set(obj, NULL);
+}
+
+static void
+_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
+{
+   INTERNAL_ENTRY;
+   sd->x = x;
+   sd->y = y;
+   _smart_reconfigure(sd);
+}
+
+static void
+_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   INTERNAL_ENTRY;
+   sd->w = w;
+   sd->h = h;
+   _smart_reconfigure(sd);
+}
+
+static void
+_smart_show(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   evas_object_show(sd->edje_obj);
+   evas_object_show(sd->event_obj);
+}
+
+static void
+_smart_hide(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   evas_object_hide(sd->edje_obj);
+   evas_object_hide(sd->event_obj);
+}
+
+static void
+_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
+{
+   INTERNAL_ENTRY;
+   evas_object_color_set(sd->edje_obj, r, g, b, a);
+}
+
+static void
+_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
+{
+   INTERNAL_ENTRY;
+   evas_object_clip_set(sd->edje_obj, clip);
+   evas_object_clip_set(sd->event_obj, clip);
+}
+
+static void
+_smart_clip_unset(Evas_Object *obj)
+{
+   INTERNAL_ENTRY;
+   evas_object_clip_unset(sd->edje_obj);
+   evas_object_clip_unset(sd->event_obj);
+}
+
+/* never need to touch this */
+
+static void
+_smart_init(void)
+{
+   if (_smart) return;
+     {
+       static const Evas_Smart_Class sc =
+         {
+            SMART_NAME,
+              EVAS_SMART_CLASS_VERSION,
+              _smart_add,
+              _smart_del,
+              _smart_move,
+              _smart_resize,
+              _smart_show,
+              _smart_hide,
+              _smart_color_set,
+              _smart_clip_set,
+              _smart_clip_unset,
+              NULL,
+              NULL,
+              NULL,
+              NULL
+         };
+       _smart = evas_smart_class_new(&sc);
+     }
+}
+
diff --git a/src/lib/els_hor_scroller.h b/src/lib/els_hor_scroller.h
new file mode 100644 (file)
index 0000000..fa5b152
--- /dev/null
@@ -0,0 +1,32 @@
+typedef enum _Elm_Very_Smart_Scroller_Policy
+{
+       ELM_VERY_SMART_SCROLLER_POLICY_AUTO,
+       ELM_VERY_SMART_SCROLLER_POLICY_ON,
+       ELM_VERY_SMART_SCROLLER_POLICY_OFF
+}
+
+Elm_Very_Smart_Scroller_Policy;
+Evas_Object *hor_elm_smart_scroller_add             (Evas *evas);
+void hor_elm_smart_scroller_child_set               (Evas_Object *obj, Evas_Object *child);
+void hor_elm_smart_scroller_extern_pan_set          (Evas_Object *obj, Evas_Object *pan, void (*pan_set) (Evas_Object *obj, Evas_Coord x, Evas_Coord y), void (*pan_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y), void (*pan_max_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y), void (*pan_child_size_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y));
+void hor_elm_smart_scroller_custom_edje_file_set    (Evas_Object *obj, char *file, char *group);
+void hor_elm_smart_scroller_child_pos_set           (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+void hor_elm_smart_scroller_child_pos_get           (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void hor_elm_smart_scroller_child_region_show       (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+void hor_elm_smart_scroller_child_viewport_size_get (Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
+void hor_elm_smart_scroller_step_size_set           (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+void hor_elm_smart_scroller_step_size_get           (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void hor_elm_smart_scroller_page_size_set           (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
+void hor_elm_smart_scroller_page_size_get           (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
+void hor_elm_smart_scroller_policy_set              (Evas_Object *obj, Elm_Very_Smart_Scroller_Policy hbar, Elm_Very_Smart_Scroller_Policy vbar);
+void hor_elm_smart_scroller_policy_get              (Evas_Object *obj, Elm_Very_Smart_Scroller_Policy *hbar, Elm_Very_Smart_Scroller_Policy *vbar);
+Evas_Object *hor_elm_smart_scroller_edje_object_get (Evas_Object *obj);
+void hor_elm_smart_scroller_single_dir_set          (Evas_Object *obj, Eina_Bool single_dir);
+Eina_Bool hor_elm_smart_scroller_single_dir_get     (Evas_Object *obj);
+void hor_elm_smart_scroller_theme_set               (Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style);
+void hor_elm_smart_scroller_hold_set                (Evas_Object *obj, Eina_Bool hold);
+void hor_elm_smart_scroller_freeze_set              (Evas_Object *obj, Eina_Bool freeze);
+void hor_elm_smart_scroller_bounce_allow_set        (Evas_Object *obj, Eina_Bool horiz, Eina_Bool vert);
+void hor_elm_smart_scroller_paging_set              (Evas_Object *obj, double pagerel_h, double pagerel_v, Evas_Coord pagesize_h, Evas_Coord pagesize_v);
+void hor_elm_smart_scroller_region_bring_in         (Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
+